# JVM内存布局 ## 总体内存概念布局 1. 线程私有数据 - 虚拟机栈 > 记录Java方法调用顺序,每调用一个方法,就会向栈中压入一个栈帧,栈帧中记录着局部变量表、操作数栈、动态链接、方法出口等信息 - 本地方法栈 > 记录native方法调用顺序,每调用一个Native方法,就会向栈中压入一个栈帧,栈帧中记录着局部变量表、操作数栈、动态链接、方法出口等信息 - 程序计数器 > 记录当前线程字节码指令执行的行号 2. 线程共享数据 - 堆 > 存储所有的类实例和数组,是JVM中占用内存最多的区域,垃圾回收主要也是在这个区域 - 方法区 > 存储Java的类元数据和运行时常量池,包括所有的类信息、常量、类变量、动态编译缓存等 ![总体内存布局](http://tuchuang.anyi.space/imgs/JVM%E5%86%85%E5%AD%98%E5%88%92%E5%88%86-JVM%E5%86%85%E5%AD%98%E5%B8%83%E5%B1%80%E5%AE%8F%E8%A7%82%E6%A6%82%E5%BF%B5%E5%88%92%E5%88%86.png) ## 虚拟机栈 虚拟机栈就是一个非常关键的部分,看名字就知道它是一个栈结构,每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(其实就是栈里面的一个元素),栈帧中包括了当前方法的一些信息,比如局部变量表、操作数栈、动态链接、方法出口等。 ![虚拟机栈](http://tuchuang.anyi.space/imgs/JVM%E5%86%85%E5%AD%98%E5%88%92%E5%88%86-%E8%99%9A%E6%8B%9F%E6%9C%BA%E6%A0%88.png) ## 本地方法栈 与虚拟机栈结构类似 ## 堆 > 堆结构在JDK1.8前后有改变,JDK1.8前堆中的永久代是方法区的实现,之后方法区使用元空间实现,不在堆内存中,使用直接内存不属于JVM内存 堆内存被划分三部分新生代、老年代、永久代;JDK1.8及之后为两部分,只有新生代和老年代,永久代被元空间取代 > 元空间在直接内存中,不属于JVM的内存 在HotSpot虚拟机中,新生代被划分为三块,一块较大的Eden空间和两块较小的Survivor空间,默认比例为8:1:1,老年代的GC评率相对较低,永久代一般存放类信息等(其实就是方法区的实现) 所有新创建的对象,在一开始都会进入到新生代的Eden区(如果是大对象会被直接丢进老年代) 在一次垃圾回收之后,Eden区域没有被回收的对象,会进入到Survivor区。在一开始From和To都是空的,而GC之后,所有Eden区域存活的对象都会直接被放入到From区,最后From和To会发生一次交换,也就是说目前存放我们对象的From区,变为To区,而To区变为From区 在Eden区的存活对象复制到From区之后,所有To区域中的对象会进行年龄判定(每经历一轮GC年龄`+1`,如果对象的年龄大于`默认值为15`,那么会直接进入到老年代,否则移动到From区) 垃圾收集分为: - Minor GC - 次要垃圾回收,主要进行新生代区域的垃圾收集。 - 触发条件:新生代的Eden区容量已满时。 - Major GC - 主要垃圾回收,主要进行老年代的垃圾收集。 - Full GC - 完全垃圾回收,对整个Java堆内存和方法区进行垃圾回收。 - 触发条件1:每次晋升到老年代的对象平均大小大于老年代剩余空间 - 触发条件2:Minor GC后存活的对象超过了老年代剩余空间 - 触发条件3:永久代内存不足(JDK8之前) - 触发条件4:手动调用`System.gc()`方法 ### JDK1.8前 ![堆-JDK1.8前](http://tuchuang.anyi.space/imgs/JVM%E5%86%85%E5%AD%98%E5%88%92%E5%88%86-%E5%A0%86-JDK1.8%E5%89%8D.png) ### JDK1.8 ![堆-JDK1.8](http://tuchuang.anyi.space/imgs/JVM%E5%86%85%E5%AD%98%E5%88%92%E5%88%86-%E5%A0%86-JDK1.8.png) ## 方法区 方法区也是整个Java应用程序共享的区域,它用于存储所有的类信息、常量、静态变量、动态编译缓存等数据,可以大致分为两个部分,一个是类信息表,一个是运行时常量池。 ![方法区](http://tuchuang.anyi.space/imgs/JVM%E5%86%85%E5%AD%98%E5%88%92%E5%88%86-%E6%96%B9%E6%B3%95%E5%8C%BA.png) ## 完整JVM内存布局 ### JDK1.8前 ![完整JVM内存布局-JDK1.8前](http://tuchuang.anyi.space/imgs/JVM%E5%86%85%E5%AD%98%E5%88%92%E5%88%86-%E5%86%85%E5%AD%98%E5%B8%83%E5%B1%80-JDK1.8%E5%89%8D.png) ### JDK1.8 ![完整JVM内存布局-JDK1.8及以后](http://tuchuang.anyi.space/imgs/JVM%E5%86%85%E5%AD%98%E5%88%92%E5%88%86-%E5%86%85%E5%AD%98%E5%B8%83%E5%B1%80-JDK1.8%E5%BC%80%E5%A7%8B.png) ## 参考资料 [柏码知识库 | JVM 笔记(二)内存管理](https://www.itbaima.cn/zh-CN/document/ydd7n3jg8unc3clg)