一、JVM运行时数据区(默认堆大小是系统内存的1/4)
1、方法区
方法区是所有线程共享的内存区域,它用于存储已被Java虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
2、堆
存放对象实例,垃圾回收的主要区域
3、虚拟机栈
虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
4、本地方法栈
native 本地方法栈
5、程序计数器
保存当前线程所正在执行的字节码指令的地址
二、直接内存
直接内存不是虚拟机运行时数据区的一部分,通过一个存储在Java堆中的DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native(本地)堆中来回复制数据
三、垃圾回收机制
1、方法栈/本地方法栈引用的对象、方法区中的静态属性/常量等都是GC Root,GC Root不可达的对象都是垃圾对象
2、堆被分为新生代和老年代(默认1:2),新生代又分为一个eden区和两个survivor区(默认8:1:1)
3、JVM 每次只会使用 Eden 和其中的一块 Survivor 区域(from)为对象分配内存,另一块survivor(to)空着,用于实现垃圾回收时的复制算法,扫描GC Root可达对象,标记存活对象,将存活对象复制到survivor(to)区域(对象年龄加1),清空Eden 和 Survivor(from)区域,from区域和to区域互相转换角色
4、survivor(to)区域对象年龄累加到一定值后(默认是15),即多次垃圾回收后仍然存活的对象就会被转到老年代中,老年代垃圾回收算法一般是标记清除和标记整理算法
5、大对象会直接放入到老年代
6、引用计数法判断对象是否存活,无法避免对象循环引用的问题,所以被淘汰了,基本都使用gc root可达性算法
7、垃圾回收算法:
标记清除:先标记,再清除,该算法会产生大量碎片内存;
标记整理:先标记,再整理(将存活对象往前移动,使内存规整无碎片)再清除后面的内存
复制算法:如上述第3点描述
四、垃圾收集器
-
新生代收集器:Serial、ParNew、Parallel Scavenge(jdk8默认)
-
老年代收集器:CMS、Serial Old、Parallel Old(jdk8默认)
-
整堆收集器:G1(jdk9默认)
-
Serial单线程收集器,它只会使用一个 CPU 或者线程去完成垃圾收集工作,而且在它进行垃圾收集时,必须暂停其他所有的工作线程
-
ParNew 收集器:Serial 的多线程版本,即同时启动多个线程去进行垃圾收集,单cpu时性能同serial一致