内存模型(HotSpot)
- 堆用来主要存放种类实例对象。
- 堆主要分为新生代(Young)与老年代(Old)。
- 新生代包含:Eden,From Survivor,To Survivor。
- 老年代主要用来保存程序声明周期长的对象。
- 永生代(Permanent):方法区,不属于java堆,另一个名字Non-Heap,指永久保存的区域,主要存放Class和Meta信息。
方法区回收
方法区回收的性价比比较低。在堆中,GC一次可以回收70%-95%空间,而永生代只能回收很少的空间。但也会执行回收,当内存严重不足时,会回收方法区的无用的常量和无用的类。
GC
MinorGC
- MinorGC发生在新生代,采用复制算法。
- Eden(包含一个survivor区域)对象初始化------>MinorGC------>如果在另一个Survivor有足够空间容纳对象,则通过复制算法把对象复制到Survivor并标记年龄为1------>清理Eden区域------>后续每次MinorGC,年龄都+1---->当到达阈值(default 15)这些对象就会晋升成为老年代。
- 如果是大对象,可能直接进入老年代。
FullGC(stop the world)
- FullGC发生在老年代,采用标记-消除或者标记-整理算法。
- 发生MinorGC前,先检查Old最大的可用连续空间>新生代所有对象之和,如果成立,则MinorGC安全,反之,会检查HandlePromotionFailure是否允许担保失败,若是,则检查Old最大可用连续空间>历次晋升到Old的对象的平均大小,如果成立,则尝试MinorGC.如果不允许担保失败,则转换为一次FullGC。
- 标记-清除算法和标记-整理算法会产生很多内存碎片,如果后续要分配一个大对象,没有足够多可用的连续空间,就会提前FullGC。
GC日志
添加vm参数:-XX:+PrintGCDetails
MinorGC
[GC [PSYoungGen: 1019K->568K(28672K)] 1019K->568K(92672K), 0.0529244 secs] [Times: user=0.00 sys=0.00, real=0.06 secs]
翻译: [GC [PSYoungGen{新生代} 1019K{MinorGC前新生代内存使用}->568K{MinorGC后新生代内存使用}(28672K{新生代总的内存大小}) 1019K{MinorGC前JVM堆内存使用的大小}->568K{MinorGC后JVM堆内存使用的大小}(92672K{堆的可用内存大小}), 0.0529244 secs{MinorGC总耗时}] [Times: user{用户耗时}=0.00 sys{系统耗时}=0.00, real{实际耗时}=0.06 secs]
FullGC
[Full GC [PSYoungGen: 568K->0K(28672K)] [ParOldGen: 0K->478K(64000K)] 568K->478K(92672K) [PSPermGen: 2484K->2483K(21504K)], 0.0178331 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]
翻译: [Full GC [PSYoungGen: 568K->0K(28672K)] [ParOldGen{老年代}: 0K{FullGC前老年代内存使用}->478K{FullGC后老年代内存使用}(64000K{老年代总的内存大小})] 568K{FullGC前JVM堆内存使用的大小}->478K{FullGC后JVM堆内存使用的大小}(92672K{堆的可用内存大小}) [PSPermGen{永久代}: 2484K->2483K(21504K)], 0.0178331 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]
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数。并行收集线程数。
其他
- -XX:PermSize=10M和-XX:MaxPermSize=10M限制方法区大小。
- -XX:MaxDirectMemorySize=10M指定DirectMemory(直接内存)容量,如果不指定,则默认与JAVA堆最大值(-Xmx指定)一样。
- -XX:+HeapDumpOnOutOfMemoryError 可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照(.hprof文件)以便时候进行分析(比如Eclipse Memory Analysis)。
参考:https://blog.csdn.net/u013256816/article/details/50764532