在前面的文章中,分析了JVM内存区域的划分,这里重点看一下堆内存的结构和垃圾回收机制
堆内存结构
heap区分为Young Gen(新生代)、老年代Old Gen(老年代),其中新生代被分为Eden Space(伊甸区)、 Survivor Space(幸存者区),依旧是我们常说的From/to区 。
我们认为永久区,这里永久区和方法区不作区分,JDK1.8之后,这一块被元数据区取代
下图形象的展示了Java堆内存的结构
垃圾回收的过程
如上图所示,Eden Space字面意思是伊甸园,对象被创建的时候首先放到这个区域
Survivor区也被称为幸存者区,在垃圾回收时,eden空间中的存活对象会被复制到未使用的Survivor空间中(假设是to区)(复制算法),正在使用的survivor空间(假设是from)中的年轻对象也会被复制到to空间中。此时,eden空间和from空间中的剩余对象就是垃圾对象,可以被直接清空。
新生代中执行的垃圾回收被称之为Minor GC(因为是对新生代进行垃圾回收,所以又被称为Young GC),每一次Young GC后留下来的对象age加1。
当老年代被放满的之后,虚拟机会进行垃圾回收,称之为Major GC。由于Major GC除并发GC外均需对整个堆进行扫描和回收,因此又称为Full GC。
堆内存参数的设置
-Xmx2g //JVM最大允许分配的堆内存,按需分配
-Xms2g //JVM初始分配的堆内存,一般和Xmx配置成一样以避免每次gc后JVM重新分配内存。
-Xmn256m //年轻代内存大小,整个JVM内存=年轻代 + 年老代 + 持久代,持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小
-XX:PermSize=128m //持久代内存大小
jdk1.8中改为元数据区
-XX:MaxMetaspaceSize=128m 设置最大的元内存空间128M
-Xss256k //设置每个线程的堆栈大小
-XX:NewRatio=4//设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6
Minor GC ,Full GC 触发条件
Minor GC触发条件:当Eden区满时,触发Minor GC。
Full GC触发条件:
(1)调用System.gc时,系统建议执行Full GC,但是不必然执行
(2)老年代空间不足
(3)方法去空间不足
(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存
(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小