北川广海の梦

北川广海の梦

浅析JVM内存模型

311
2020-05-22

内存区域

JVM其实也是一个程序,向操作系统申请内存,然后将这些内存,划分为不同的区域。
以线程的角度看,分为线程私有和线程公有。

线程私有

1.虚拟机栈
2.本地方法栈
3.程序计数器

线程公有

1.堆
2.方法区
3.直接内存(堆外内存)

区域

虚拟机栈

Java语言的执行,并不是传统的CPU直接执行汇编代码,而是由JVM解释执行字节码指令。而每一次的方法调用,也就对应了一次虚拟机栈的入栈出栈。
虚拟机栈中存放的东西叫做栈帧
栈帧包含一下几个部分
1.局部变量表:
存放了各种局部变量,以及对象的引用,它的大小在编译的时候,就可以被确定。

2.操作数栈:
操作数栈又可以称为表达式栈,
例如简单的一句:

	int i=0;

就对应着先将0这个值,压入操作数栈,然后将栈顶的值赋值给i这个局部变量。
方法中的各种算数运算,都是靠操作数栈实现的。

3.动态链接:
一个方法要调用另外的方法,就需要得到被调用方法的地址,这一过程就叫链接,也就是将方法的符号,转化为方法的引用。静态方法,私有方法,构造函数的地址会在类加载过程中,就完成链接,这样的过程被称为静态链接。而虚方法(Java默认实例方法都是虚方法,.NET需要添加virtual关键字)在编译时并不知道它是引用的哪一个方法,可能是不同的实现类(多态)。而在运行时解析方法的引用的过程,就叫做动态链接。

4.方法返回
Java中,有两种方式退出当前方法。
一种时正常返回,这时根据方法的定义,来决定是否要将返回值返回(将返回值压入调用者的操作数栈),另一种是通过异常退出,这种情况不会将返回值赋值给调用者。但是两种方式退出方法后,都需要返回到调用者调用的地方,程序才能继续执行。如果是正常返回,那么执行完当前方法,就应该继续执行调用方法的下一条指令了,而这个下一条指令可以通过主调方法的PC计数器得到。所以在调用方法,创建栈帧的时候,将主调方法的程序计数器保存在栈帧中,就可以在调用完成后继续执行。而如果是异常退出,此时返回地址是要通过异常处理器表来确定,栈桢一般不会保存这部分信息。

本地方法栈

本地方法栈的用途很显然,也是用于调用方法的。不过它并不是执行Java方法,而是native方法,例如C/C++实现的方法。当调用本地方法时,Java虚拟机栈会不会改变,jvm会通过动态链接的方式,获取到本地方法的地址,并开始执行。

程序计数器

这是虚拟机中唯一不会出现OutOfMemoryError的区域。它的生命周期和线程同步,线程生,则它生,线程死则它死。它的作用就是确定下一个应该执行的指令是什么,它几乎和汇编中的pc寄存器作用一模一样。它的作用主要有两个:
1.虚拟机靠它来依次读取指令并执行,实现程序的流程控制,例如顺序执行,选择,循环,异常处理等等。
2.在多线程运行的情况下,每个线程被重新得到CPU时间片的时候,可以知道自己执行到哪里了,快速的恢复。

堆是JVM内存区域中最大的一块,这块区域的最大作用就是存放对象的实例,并且数组也是在这里存放的。当并非绝对,在适当的时候,也是可以在栈内分配对象。当对象的作用域仅仅位于某一个区域,并且在外部没有引用它,则可能将它在栈内分配。堆也是Java垃圾收集器主要作用的地方。对于这里的对象,在合适的时候,GC就会对它们进行回收。原本堆可分为大致三个部分:
1.新生代
2.老年代
3.永久代

但在JDK1.8中,移除了永久代,取而代之的是使用直接内存的元空间。

新生代中可分为eden,survivor0,survivor1。它们的大小占比默认为
8:1:1
大部分对象都是直接在eden区域进行分配的。在经历了一次垃圾回收之后,如果它还存活,就会进入survivor0或者survivor1区域。并且对象的年龄会加1。
当对象年龄到达一定阀值之后,就会进入老年代。
但也存在当一个对象比较大的时候,直接分配在老年代的情况。

方法区

方法区与永久代和元空间的关系,就相当于标准和实现。JVM定义了方法区这一标准,而永久代和元空间只是不同的实现方式而已。
元空间是直接分配于直接内存当中的。
方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。并且在JDK1.7中,字符串常量池被存放到了堆中。

直接内存

JDK1.4 中新加入的 NIO(New Input/Output) 类,引入了一种基于通道(Channel) 与缓存区(Buffer) 的 I/O 方式,它可以直接使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样就能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆之间来回复制数据。