JVM内存详解

JVM内存详解

Java虚拟机的运行时内存空间可以分成五个部分

  • 程序计数器
  • 虚拟机栈
  • 本地方法栈
  • 方法区

内存划分示意图:

程序计数器

作用

  • 当前线程所执行的字节码的行号指示器
  • 通过改变程序计数器的值来选取下一条要执行的字节码指令。
  • 程序的分支,跳转,循环,异常处理,线程恢复依赖于程序计数器完成。

特性

  • 是线程私有的,记录线程当前执行的位置。
  • 若线程执行的是Java方法,则程序计数器记录的是字节码指令的地址;若执行的是Native方法,则计数器值为空。

虚拟机栈

定义

  • 描述方法执行的内存模型。
  • 虚拟机栈中保存着一个个栈帧,一个栈帧对应于一个方法。
  • 一个方法被线程执行,则JVM创建一个栈帧,并将栈帧入栈;若一个方法执行完成,则对应的栈帧从虚拟机栈中出栈
  • 每个栈中包含的内容:
    • 局部变量表
    • 操作数栈
    • 动态链接
    • 方法出口

特性

  • 虚拟机栈是线程私有的,一个线程拥有一个虚拟机栈。

局部变量表

  • 局部变量表存放编译时期可知的:
    • 基本数据类型
    • 对象引用
    • returnAddress类型
  • 局部变量表所需的内存空间在编译时期完成分配,完全确定,运行时不改变。
  • 对象引用:(也叫reference类型),本质是一个地址,指向一个对象的起始地址一个代表对象的句柄
  • returnAddress类型:本质是一个地址,指向一条字节码执行。

可能的异常

  • StackOverFlow异常:请求的栈深度大于允许的最大深度。
  • OutOfMemory异常,内存已用完,且无法扩展栈深度。

本地方法栈

  • 类似于虚拟机栈,是用来存放Native方法的相关信息。

定义

  • 用来存放大部分的对象实例数组

特性

  • 在堆中声明的对象不能直接访问,需通过虚拟机栈中对应的引用变量访问堆中的对象或数组。
  • 所有线程共享的内存区域。
  • 占JVM内存中的最大一部分。
  • 物理上非连续,逻辑上连续。
  • 垃圾回收的主要区域,也称GC堆。

可能的异常

  • OutOfMemoryError异常:内存用完了。

方法区

定义

  • 用来存储已被JVM加载的:
    • 类的信息
    • 常量
    • 静态变量
    • 编译后的代码

特性

  • 是各个线程共享的内存区域。
  • 物理上不需要连续的内存空间。
  • 大小可以固定,也可扩展。
  • 可以不实现垃圾回收(数据非永久存在,回收主要是常量池的回收和类型的卸载)。

运行时常量池

定义 常量池中存放编译时期产生的各种字面量符号引用

特性

  • 可以在运行时将新的常量放入方法区的运行时常量池中。

如: String类中的intern方法:若常量池中已包含指定的字符串,则返回常量池中的字符串;否则,将指定的字符串加入常量池中,并返回此字符串对象的引用。

可能的异常

  • OutOfMemoryError异常:常量池无法申请内存时。

直接内存

NIO引入了一种基于通道和缓冲区的IO方式,它可以使用本地函数直接分配堆外内存,然后通过一个存储在堆里的DirectByteBuffer对象作为这块内存的引用来操作堆外内存中的数据。

直接内存不受Java堆大小的限制,但仍然受本机总内存的限制。

可能的异常

  • OutOfMemoryError异常

class son extends father{ // 子类,存放于堆中
    static int var1; // 静态成员变量,存放于方法区
    static father var2; // 静态成员变量,存放于堆中
    final double var3=3.14; // 常量,存放于方法区
    
    void method1(){ // 方法,存放于虚拟机栈中
        int var4; // 局部变量,存放于虚拟机栈的局部变量表中
        father var5 = new father(); // 局部引用变量var5存放于虚拟机栈的局部变量表中,指向的对象存放在堆中
    }
}

class father{
    static int var1;
    
    void method1(){
        int var2;
    }
}

JDK8的改动

  • 取消“永久代”,使用“元空间”(metaspace)。
  • 静态成员变量中。
  • 方法区是JVM规范,永久区方法区的具体实现。

内存的划分:

  • 虚拟机内存:
    • 程序计数器
    • 虚拟机栈
    • 本地方法栈
    • 堆(常量池,静态成员变量,对象,数组
  • 本地内存
    • 元空间

JDK8内存分配

参考:

原文地址:https://www.cnblogs.com/truestoriesavici01/p/13224704.html