java堆是java虚拟机管理的最大的一块内存区域,该区域为所有线程共享并且主要用于存放java实例对象。大小可通过–Xms和–Xmx两个参数进行设置
堆被分为新生代 ( Young )、老年代 ( Old )两个不同的区域,其中默认情况下新生代占堆的1/3,老年代占2/3。通过–XX:NewRatio可设置新生代与老年代比例。
java堆中的垃圾回收:分Minor GC、Full GC(Major GC)两种
2、新生代
新生代可通过–Xmn参数设置具体大小。其被划分为三个区域:Eden、From Survivor、To Survivor 。 默认 Edem : from : to = 8 : 1 : 1,可以通过设置参数–XX:SurvivorRatio改变其大小。
JVM 每次只会使用 Eden 和其中的一块 Survivor 来存储,而另一块 Survivor 区域空闲,因此JVM中新生代真正能使用的内存大小需减去一块 Survivor的大小。
基本上所有java实例对象创建的时候都是存放在新生代,并且多数存活时间不长,因此该区域会频繁发生垃圾回收。在新生代采用的是Minor GC,这种垃圾收集方式采用了复制算法。当某些对象在Eden和其中一块Survivor区域创建之后,发生了一次Minor GC,但这些对象仍然存活并且能够被另外一块 Survivor 区域所容纳,则通过复制算法将存活的对象复制到另外一块 Survivor(当另外一块 Survivor没法容纳时将其存放到为新生代担保的老年代中),之后清理开始使用的Eden和Survivor区域,并将这些对象的年龄设置为1。之后每发生一次Minor
GC并且对象能存活则其年龄加1,默认当年龄为15则对象会被放到老年代,可以通过设置-XX:MaxTenuringThreshold的大小来修改这个年龄的大小。
3、老年代
如果新生代的对象经过一段时间的垃圾回收之后仍然存活,则会进入到老年代,或者当对象比较大( 即需要分配一块较大的连续内存空间 ),则直接在创建的时候就进入老年代。
老年代采用的是Full GC,这种垃圾收集方式采用了标记-清除算法。因为老年代的对象存活时间的比较久,并且对象一般比较多、比较大。所以进行垃圾收集的时候一般回收的资源较少,一次Full GC的操作时间比较长。因此Full GC 发生的次数不会有Minor GC那么频繁。
备注:
复制算法:复制算法简单的讲就是将内存分为两部分,一部分使用,一部分空闲,当发生垃圾收集的时候把正在使用的区域中的存活对象复制到空闲区域,然后清空使用区域。
标记-清除算法:将老年代中需要清除的对象进行标记,在进行GC的时候则对标记的对象进行回收。
部分参数说明:
-Xms 初始堆大小 如:-Xms256m
-Xmx 最大堆大小
-Xmn 新生代大小
-XX:NewRatio 新生代与老年代比例,如 –XX:NewRatio=4,则新生代与老年代为1:4。
-XX:SurvivorRatio 新生代Eden与Survivor的比例,如–XX:SurvivorRatio=3,则Edem : from : to=3:1:1。
-XX:+PrintGCDetails 打印GC信息
GC信息分析:
1、[GC [PSYoungGen: 33198K->1982K(36416K)] 33198K->1982K(119680K), 0.0016250 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
2、[PSOldGen: 33198K->1982K(36416K)] 33198K->1982K(119680K)
分析:
1、[GC [PSYoungGen: 1K->2K(3K)]4K->5K(6K),7
secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
此为新生代的MinorGC,其中1表示MinorGC前新生代的使用量,2表示MinorGC后新生代的使用量,3表示新生代的内存总量, 4表示MinorGC前堆的使用量,5表示MinorGC后堆的使用量,6表示堆的可用量,7表示MinorGC总耗时
2、[PSOldGen: 1K->2K(3K)]4K->5K(6K)
此为老年代的FullGC,其中1表示FullGC前老年代的使用量,2表示FullGC后老年代的使用量,3表示老年代的内存总量, 4表示FullGC前堆的使用量,5表示FullGC后堆的使用量,6表示堆的可用量