欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【深入理解JVM】JVM的内存结构(堆、栈、GC)

程序员文章站 2022-06-07 08:01:10
...


  最近一直在看JVM相关的东西,在这里整理一下,方便以后复盘,有错误的地方欢迎留言。

Java跨平台

  不同操作系统使用的指令不同,JVM屏蔽了操作系统的差异,不同JDK适应不同的操作系统,使Java具有跨平台的特性。

JVM的组成

JVM由四部分组成:

  • 类加载器
  • 运行时数据区
  • 执行引擎
  • 本地接口

运行时数据区

  由 堆、栈、程序计数器、本地方法栈、方法区 五部分组成。
【深入理解JVM】JVM的内存结构(堆、栈、GC)
【深入理解JVM】JVM的内存结构(堆、栈、GC)由线程共享
【深入理解JVM】JVM的内存结构(堆、栈、GC)由线程独有,每个线程都包含 栈、程序计数器、本地方法栈。

【深入理解JVM】JVM的内存结构(堆、栈、GC)
线程中每执行一个方法,栈中进入一个栈帧,栈帧由四部分组成。

  • 局部变量表
  • 操作数表
  • 动态链接
  • 方法出口
public class Test{
    public static void main(String[] args){
         int i = 1;
         int j = 2;
         int k = i + j;
         System.out.println(k);
    }
}

由Test.java说明程序运行时栈中情况。
javac Test.java 编译成Test.class。
javap -c Test.class>Test.txt 将字节码反编译结果输出到Test.txt文件中,内容如下:

Compiled from “Test.java”
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object.""????)V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: istore_3
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_3
12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
15: return
}

可以去下列网址查看 iconst_1 JVM字节码指令的含义
https://www.cnblogs.com/tenghoo/p/jvm_opcodejvm.html

大致意思:
  把1放入操作数栈,将1赋给变量 i 存入局部变量,j 同理,将1和2相加为3再赋给变量k。

  程序计数器会记录将要执行的指令行号,这样在挂起后恢复时就可以知道上次执行的位置。

栈帧中的动态链接

这就要说一下静态链接,在类加载过程中包含如下步骤:
【深入理解JVM】JVM的内存结构(堆、栈、GC)
  静态链接在加载过程,字节码文件的符号被加载到方法区,期间需要静态链接把符号引用转为直接引用,字节码符号无法直接使用,直接引用类似于地址,这样才可以使用。

  动态链接是在运行时将符号引用转为直接引用。
  方法出口可以理解为方法的 return。

本地方法栈

  在Java之前使用C的很多,Java有些也是用C实现的,Java中也有 native修饰的方法,这样的方法就是用C实现的,这些字符存在本地方法栈中,执行引擎会找C语言的函数库(.dll)。

执行引擎

执行引擎执行字节码的方式:

  • 解释执行:一行一行边翻译边执行
  • JIT即时编译执行:这里有热点代码的概念,被多次调用的方法或被多次执行的循环体视为热点代码,热点代码会被编译执行,这样效率高点

堆和Full GC

【深入理解JVM】JVM的内存结构(堆、栈、GC)
堆 由年轻代、老年代组成。在JVM启动时创建,是GC垃圾回收的主要对象,也是分配存储区最大的一块。
年轻代 由Eden区(伊甸区)、From Survivor、To Survivor组成。

这里需要说一下轻GC(Minor gc)和Full GC。

  • 新创建的对象需要放入Eden区,当Eden区满后,GC回收没有被引用的对象,剩余对象放到From Survivor区;
  • 当From Survivor区满后,清空From Survivor区,未被回收的对象放入To Survivor区;
  • 此时From和To身份互换,From变为To,To变为From,如此循环15次(默认15次),当To区满时,将未被清理的对象放入老年代;
  • 当老年代满时,触发Full GC(之前都是Minor GC),由于不同的垃圾回收器机制不同,可能把之前的区都清理,也可能只清理老年区(涉及到垃圾回收器和算法,以后再写一篇补上)。

堆、栈、方法区的爱恨纠葛

【深入理解JVM】JVM的内存结构(堆、栈、GC)
   s 学生变量存在栈中,在堆中创建对象,将对象的地址赋给s变量;
堆中的对象实例指向方法区的类模板,通过类模板创建实例对象。