JAVA垃圾收集器详解

1.基于HotSpot虚拟机1.6版Update22,包含的虚拟机如下
新生代收集器(采取复制算法):
Serial
(1)单线程收集器(只会只用一个CPU或一条手机线程去完成垃圾收集工作,
并且在进行垃圾收集的时候,必须暂停其他所有的工作线程“Stop The World”:这一点用户体验恶劣)
(2)优点:在单个CPU环境下,简单而高效
缺点:用户体验差(比如每工作1小时暂停响应5分钟)

parNew
(1)Serial的多线程版本(在低CPU的情况下,效果没有Serial效果好),能与CMS搭配使用

Parallel Scavenge:
(1)并行多线程收集器
(2)目标:达到可控制的吞吐量。(停顿时间越短就越适合需要与用户交互的程序,良好的响应速度
能够提升用户体验;而高吞吐量则可以最高效率地利用CPU时间,尽快完成程序的运行任务,
主要适合在后台运算而不需要太多的交互的任务)
两个参数用于精确控制吞吐量:最大垃圾收集停顿时间:-XX:MaxGCPauseMillis (大于0的ms)
设置吞吐量大小:-XX:GCTimeRatio (>0 && < 100)
-XX:_+UseAdaptiveSizePolicy 自动调控,设置上 面的参数之一即可

老年代收集器:
SerialOld(MSC)

(1)单线程收集器
(2)标记整理算法
(3)在jdk1.5与Parallel Scavenge搭配使用,作为CMS收集器的后备预案

Parallel Old
(1)多线程
(2)标记整理算法
(3)jdk1.6之后:与parallel Scavenge搭配使用,“吞吐量优先“收集器终于有了名副其实的组合

CMS:
(1)目标:尽可能缩短垃圾收集时用户线程的停顿时间。
(2)标记清除算法
(3)过程:初始标记->并发标记->重新标记->并发清除
(4)对CPU资源十分敏感。默认启动回收线程数:(CPU数量+3)/4
当cpu在4个以上时,并发回收时垃圾收集线程最多占用不超过25%的CPU资源,
但是当cpu不足4个的时候,CMS对用户程序的影响可能会很大。
(5)无法清理浮动垃圾
(6)标记清除算法:收集结束时会产生大量的空间碎片。


G1(Garbage First):
(1)基于标记整理算法
(2)非常精确地控制停顿,即能让使用者明确指定在一个长度为M毫秒的时间判断内,
消耗在垃圾收集上的时间不得超过N毫秒,这几乎是实时java(RTSJ)的垃圾收集器的特征了
(3)新生代,老年代都可以使用

如下图所示:两个收集器之间存在连线,就说经他们之间可以搭配使用
JAVA垃圾收集器详解_第1张图片
-Xms 最小堆,-Xmx最大堆
当最小堆占满后,会尝试进行GC,如果GC之后还不能得到足够的内存(GC未必会收集到所有当前可用内存),分配新的对象,那么就会扩展堆,如果-Xmx设置的太小,扩展堆就会失败,导致OutOfMemoryError错误提示。

-Xss128k: 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。

本机的垃圾收集器:Parallel Scavenge + SerialOld

线上jvm设置
java
-Denv=PRO
-server
-Xms4g (最小堆的大小, 也就是当你的虚拟机启动后, 就会分配这么大的堆内存给你)
-Xmx4g (是最大堆的大小 )
-Xmn2g (设置年轻代大小为2G)
-XX:MaxDirectMemorySize=512m (设置java堆外内存的峰值)
-XX:MetaspaceSize=128m 设置类元空间大小
-XX:MaxMetaspaceSize=512m 设置最大的本地内存类元空间可用于垃圾回收
-XX:-UseBiasedLocking 使用偏向锁
-XX:-UseCounterDecay
-XX:AutoBoxCacheMax=10240
-XX:+UseConcMarkSweepGC 使用cms垃圾回收器
-XX:CMSInitiatingOccupancyFraction=75 (是指设定CMS在对内存占用率达到75%的时候开始GC(因为CMS会有浮动垃圾,所以一般都较早启动GC)
-XX:+UseCMSInitiatingOccupancyOnly (只是用设定的回收阈值(上面指定的75%),如果不指定,JVM仅在第一次使用设定值,后续则自动调整.)
-XX:MaxTenuringThreshold=6
-XX:+ExplicitGCInvokesConcurrent
-XX:+ParallelRefProcEnabled
-XX:+PerfDisableSharedMem
-XX:+AlwaysPreTouch (在调用main函数之前,使用所有可用的内存分页。这个选项可以用来测试长时间运行的系统,所有的内存都已被分配。默认这个选项 是关闭的,也就是不会使用所有的内存分页。 )
-XX:-OmitStackTraceInFastThrow 省略异常栈信息从而快速抛出(如果检测到在代码里某个位置连续多次抛出同一类型异常的话,C2会决定用Fast Throw方式来抛出异常,而异常Trace即详细的异常栈信息会被清空。这种异常抛出速度非常快,因为不需要在堆里分配内存,也不需要构造完整的异常栈信息)
-XX:MaxTenuringThreshold=2 在新生代中对象存活次数(经过Minor GC的次数)后仍然存活,就会晋升到旧生代。
-XX:+ExplicitGCInvokesConcurrent (当调用System.gc()的时候, 执行并行gc。默认是不开启的,只有使用-XX:+UseConcMarkSweepGC选项的时候才能开启这个选项。)
-XX:+ParallelRefProcEnabled (1.如果应用有很多的Reference or finalizable objects,那么可以使用-XX:+ParallelRefProcEnabled来减少duration)(2.支持并发引用处理)
-XX:+HeapDumpOnOutOfMemoryError dump出当前的内存堆转储快照。
-XX:HeapDumpPath=/home/devjava/logs/ 文件是一个二进制文件,它保存了某一时刻JVM堆中对象使用情况
-Xloggc:/home/devjava/logs/lifecircle-usercore-gc.log gc日志
-XX:+PrintGCApplicationStoppedTime 打印gc一共停顿了多长时间
-XX:+PrintGCDateStamps 打印gc时间戳
-XX:+PrintGCDetails 打印gc详细信息
-jar /home/devjava/lifecircle-usercore/app/lifecircle-usercore.jar

参数详解:
-XX:+AlwaysPreTouch
JAVA进程启动的时候,虽然我们可以为JVM指定合适的内存大小,但是这些内存操作系统并没有真正的分配给JVM,而是等JVM访问这些内存的时候,才真正分配,这样会造成以下问题。
1、GC的时候,新生代的对象要晋升到老年代的时候,需要内存,这个时候操作系统才真正分配内存,这样就会加大young gc的停顿时间;
2、可能存在内存碎片的问题。

你可能感兴趣的:(JVM)