垃圾回收机制:java内存包括堆、栈、元数据区
栈:线程工作的地方
元数据区:存放加载的Class以及一些元数据的信息。
堆分代说明:
堆:分为新生代、年老代(存放存活时间比较长的对象)
新生代分为 E区、S1区、S2区
新生代:年老代=1:2 即新生代为堆的1/3 , 年老代为总内存的2/3(可以通过 –XX:NewRatio )
新生代的比值为 8:1:1 ,即E区占新生代的8/10 ,其余内存两个s区各为一半(通过 –XX:SurvivorRatio设定)
新生代每个区域满了都会触发Minor的GC,每次存活对象都会通过拷贝算法进入到下个区域,最终进入年老代
当年老代满了就会触发FullGC,时间比较长会影响系统服务,尽量避免。
打印参数说明: -XX:+PrintGCDetails
可以打印虚拟机的垃圾回收情况,MinorGC只会影响年轻代内存,Full GC会影响年轻代、年老代和元数据的内存情况。
PSYoungGen 年轻代
ParOldGen年老代
Metaspace(保存一些常量和类对象): 元数据区
代码:
/**
* -Xms60m -Xmx60m -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:+PrintGCDetails
堆最小 、最大堆、新生代大小、年轻代与年老代比值1:2 、 s区与E区比值1:8:8 ,打印GC详细
* @author admin
*/
public class TestGC2 {
public static void main(String[] args) {
Integer M = new Integer(1024 * 1024 * 1); // 单位, 兆(M)
byte[] bytes = new byte[1 * M]; // 申请 1M 大小的内存空间
bytes = null; // 断开引用链
System.gc(); // 通知 GC 收集垃圾
System.out.println();
bytes = new byte[1 * M]; // 重新申请 1M 大小的内存空间
bytes = new byte[1 * M]; // 再次申请 1M 大小的内存空间
System.gc();
System.out.println();
}
}
日志以及解释:
日志解释:
[GC (System.gc()) [PSYoungGen: 2621K->600K(37888K)] 2621K->608K(123904K), 0.0009580 secs] [Times: user=0.00 sys=0.00, real=0.05 secs]
{ [GC [新生代: MinorGC前新生代内存使用->MinorGC后新生代内存使用(新生代总的内存大小)]
MinorGC前JVM堆内存使用的大小->MinorGC后JVM堆内存使用的大小(堆的可用内存大小),
MinorGC总耗时] [Times: 用户耗时=0.00 系统耗时=0.00, 实际耗时=0.06 secs] }
[Full GC (System.gc())
[PSYoungGen: 600K->0K(37888K)]
[ParOldGen: 8K->530K(86016K)] 608K->530K(123904K),
[Metaspace: 2641K->2641K(1056768K)], 0.0065158 secs]
[Times: user=0.00 sys=0.00, real=0.01 secs]
{ [Full GC [PSYoungGen: 568K->0K(28672K)]
[老年代: FullGC前老年代内存使用->FullGC后老年代内存使用(老年代总的内存大小)] FullGC前JVM堆内存使用的大小->FullGC后JVM堆内存使用的大小(堆的可用内存大小)
[元数据区: 2484K->2483K(21504K)], 0.0178331 secs]
[Times: user=0.01 sys=0.00, real=0.02 secs]}
打印出来的GC详细信息,各个区占用的内存情况,可以计算出各个区占用内存的比例情况,验证设置的参数正确性
Heap
PSYoungGen total 18432K, used 164K [0x00000000fec00000, 0x0000000100000000, 0x0000000100000000)
eden space 16384K, 1% used [0x00000000fec00000,0x00000000fec29100,0x00000000ffc00000)
from space 2048K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x0000000100000000)
to space 2048K, 0% used [0x00000000ffc00000,0x00000000ffc00000,0x00000000ffe00000)
ParOldGen total 40960K, used 1553K [0x00000000fc400000, 0x00000000fec00000, 0x00000000fec00000)
object space 40960K, 3% used [0x00000000fc400000,0x00000000fc584730,0x00000000fec00000)
Metaspace used 2649K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 286K, capacity 386K, committed 512K, reserved 1048576K
附:JVM常用参数
-XX:+<option> 启用选项
-XX:-<option>不启用选项
-XX:<option>=<number>
-XX:<option>=<string>
堆设置
-Xms :初始堆大小
-Xmx :最大堆大小
-Xmn:新生代大小。通常为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90%
-XX:NewSize=n :设置年轻代大小
-XX:NewRatio=n: 设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n :年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:PermSize=n 永久代(方法区)的初始大小
-XX:MaxPermSize=n :设置永久代大小
-Xss 设定栈容量;对于HotSpot来说,虽然-Xoss参数(设置本地方法栈大小)存在,但实际上是无效的,因为在HotSpot中并不区分虚拟机和本地方法栈。
-XX:PretenureSizeThreshold (该设置只对Serial和ParNew收集器生效) 可以设置进入老生代的大小限制
-XX:MaxTenuringThreshold=1(默认15)垃圾最大年龄 如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代. 对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活 时间,增加在年轻代即被回收的概率
该参数只有在串行GC时才有效.
收集器设置
-XX:+UseSerialGC :设置串行收集器
-XX:+UseParallelGC :设置并行收集器
-XX:+UseParallelOldGC :设置并行年老代收集器
-XX:+UseConcMarkSweepGC :设置并发收集器
垃圾回收统计信息
-XX:+PrintHeapAtGC GC的heap详情
-XX:+PrintGCDetails GC详情
-XX:+PrintGCTimeStamps 打印GC时间信息
-XX:+PrintTenuringDistribution 打印年龄信息等
-XX:+HandlePromotionFailure 老年代分配担保(true or false)
-Xloggc:gc.log 指定日志的位置
并行收集器设置(用户线程会暂停)
-XX:ParallelGCThreads=n :设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n :设置并行收集最大暂停时间
-XX:GCTimeRatio=n :设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
并发收集器设置(程序不会暂停)
-XX:+CMSIncrementalMode :设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n :设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。