gc
垃圾收集器 串行 并行 并发CMS G1 java -XX:+PrintCommandLineFlags -version 查看默认收集器 jinfo -flags <PID> 查看服务的收集器 netstat -ano|findstr :8801 根据端口查看进程id java8默认收集器: -XX:+UseParallelGC 多线程并行收集器使用copying算法 java17默认收集器: -XX:+UseG1GC -XX:+UseParNewGC 设置年轻代为并发收集 -XX:+UseConcMarkSweepGC 设置年老代为并发收集,即CMS,加完该设置自动添加-XX:+UseParNewGC设置 CMS是老年代的一种收集器使用标记-清除算法 Mark-Sweep 适用长生命周期对象多的应用 默认是串行 Mark-Compact 标记-压缩算法 -Xmx 最大堆大小 -Xms 最小堆大小 -Xss 每个线程的堆栈大小 -Xmn 年轻代大小 -XX:SurvivorRatio 来控制Eden和Survivor的比例 -XX:+UseConcMarkSweepGC 设置年老代为并发收集 -XX:NewRatio=4的配置失效 此时年轻代大小最好用-Xmn设置 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize 设置元空间初始大小以及最大可分配大小 元数据(Metadata)是描述数据的数据,比如注解 JVM设置 1、-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -Xms512m -Xmx512m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC 2、-Xms4096M -Xmx4096M -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+DisableExplicitGC -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=50 Eden区达到2454M触发yongGC 3、-Xms10240M -Xmx10240M -XX:+UseG1GC -XX:G1HeapRegionSize=8m -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=50 -XX:+PrintGCDetails -XX:+PrintGCDateStamps Eden区达到6136M触发yongGC 新生代占用总堆内存的60%,Eden满了触发GC 16G 4、-Xms12288M -Xmx12288M -Xmn4096m -XX:+UseG1GC -XX:G1HeapRegionSize=8m -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=70 -XX:+PrintGCDetails -XX:+PrintGCDateStamps Eden区达到4088M触发yongGC G1不再像上文所述的垃圾收集器,需要分代配合不同的垃圾收集器 其他参数: -XX:NewRatio=2,新生代:老年代=1:2 ParallelGC默认比例 468:683 7:10 NewRatio值越大,老年代的大小就越大,新生代则越小。NewRatio设置为2或3时整个GC状态会更好些。由于新生代最小,GC时间最短,NewRatio=4是最佳的选择。在使用该选项后,服务器没有再发生Full GC -XX:SurvivorRatio 来控制Eden和Survivor的比例 ParallelGC默认 394:74 6:1 -XX:+DisableExplicitGC 手动调用System.gc()就不会生效 -XX:newSize 表示新生代初始内存的大小,应该小于 -Xms 的值 -Xmn 这个参数是一个快捷方式,它同时设置新生代的初始化大小和最大大小; -XX:MaxnewSize:表示新生代可被分配的内存的最大上限;当然这个值应该小于 -Xmx 的值; CMSInitiatingOccupancyFraction 触发CMS收集器的内存比例。比如60%的意思就是说,当内存达到60%,就会开始进行CMS并发收集 MaxPermSize 是 Java 虚拟机(JVM)中的一个参数,用于指定永久代(PermGen space)的最大大小。在 Java 8 之后,永久代已经被元空间(Metaspace)取代 64位系统,不指定初始内存,使用最大物理内存
GC过程
大多数新创建的对象都分配在Eden区 在经历一次Eden区的GC之后,幸存的对象将被移动到 Survivor区中的一个区(这个区已经有其他幸存对象存在) 一旦一个Survivor区满了,幸存的对象将被移动到另一个Survivor区,然后,这个满的Survivor区将被设置重新可用的状态 那些经历上述步骤一定次数的对象将被移动到老年代 通过这些步骤你可以发现,Survivor区中的一个区必须保持空白。如果Survivor的两个区都存在数据或者没有任何一个区存在数据,这将是 系统出现问题的标志 新对象是在Eden区中进行分配,在Survivor区存活时间足够长的对象将被从Survivor区移动到老年代。
堆的分区
堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,最后Survivor由FromSpace和ToSpace组成。
新生代:新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代
大小可以由-Xmn来控制,也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例
旧生代。用于存放新生代中经过多次垃圾回收仍然存活的对象
年轻代:大部分新创建的对象都分配在这里,由于大多数对象很快将变得不可达,因此许多新对象都分配在年轻代中。当新对象从年轻代消失时,我们说发生了 年轻代GC(Minor GC)。
老年代:那些没有变得不可达而且从年轻代幸存下来将被移动到老年代。老年代空间比年轻代大很多,由于它的空间比较大,GC发生的频率也要比年轻代低。当对象从老年代消失时,我们会说发生了 老年代GC(Major GC) 或 full GC。使用标记-清除算法,当老年代也没有内存分配给新来的对象的时候,就会抛出OOM(Out of Memory)异常
jc监控
二,jvm垃圾搜集参数
-verbose:gc 显示垃圾收集信息(在虚拟机发生内存回收时在输出设备显示信息)
以下选项可以和 -verbosegc 结合使用:
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-XX:+PrintGCDateStamps
打印信息[Full GC 1224K->1113K(123584K), 0.0120528 secs]
箭头(->)前后的数据1224K和1113K分别表示垃圾收集GC前后所有存活对象使用的内存容量,说明有1224K–1113K = 111K大小的对象被回收,括号内的数据 123584K为堆内存的总容量,收集所需的实际为 0.0120528秒。
选择要运行的源文件,右键选择Run As -> Run Configurations -> Arguments
在 VM argument 输入框中输入要运行的命令
回收器设置
https://blog.csdn.net/chengxuyuan_110/article/details/81033969
gc设置 在bin下的catalina.bat文件中echo Using CATALINA_BASE: "%CATALINA_BASE%"的前一行加入如下代码
set JAVA_OPTS=%JAVA_OPTS%
-server -Xms8192m -Xmx8192m -Xmn1890m -verbose:gc
-XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=5 -XX:+ExplicitGCInvokesConcurrent -XX:GCTimeRatio=19 -XX:CMSInitiatingOccupancyFraction=70 -XX:CMSFullGCsBeforeCompaction=0 -Xnoclassgc -XX:SoftRefLRUPolicyMSPerMB=0
-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/usr/local/tomcat7/logs/gc/vm.log
类别 参数 备注
Serial GC -XX:+UseSerialGC
Parallel GC -XX:+UseParallelGC -XX:ParallelGCThreads=value
Parallel Compacting GC -XX:+UseParallelOldGC
CMS GC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=value -XX:+UseCMSInitiatingOccupancyOnly
G1 -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC 在JDK6,这两个参数必须同时使用
可自主设置垃圾收集器,不同的垃圾收集器代表不同的回收算法,由jvm决定
默认GC java -jar -Xms1024m -Xmx1536m -XX:PermSize=128M -XX:MaxPermSize=256M -verbose:gc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=F:\study-idea\space\myboot\target\gc\vm.log myboot-0.0.1.jarParallel GC
G1:java -jar -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC myboot-0.0.1.jar
CMS:java -jar -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=3 -XX:+UseCMSInitiatingOccupancyOnly myboot-0.0.1.jar
Mark-Sweep GC
windows查看线程 netstat -ano | findstr 9990
jmap -heap 8808 可查看当前回收器
java -XX:+PrintCommandLineFlags -version jdk8 默认回收器 -XX:+UseParallelGC
回收器分类
https://blog.csdn.net/yrwan95/article/details/82829186 https://www.cnblogs.com/jack204/archive/2012/07/02/2572934.html
典型的垃圾收集器
垃圾收集算法是 内存回收的理论基础,而垃圾收集器就是内存回收的具体实现。下面介绍一下HotSpot(JDK 7)虚拟机提供的几种垃圾收集器,用户可以根据自己的需求组合出各个年代使用的收集器。
1.Serial/Serial Old收集器 是最基本最古老的收集器,它是一个单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial收集器是针对新生代的收集器,采用的是Copying算法,Serial Old收集器是针对老年代的收集器,采用的是Mark-Compact算法。它的优点是实现简单高效,但是缺点是会给用户带来停顿。
2.ParNew 收集器 是Serial收集器的多线程版本,使用多个线程进行垃圾收集。
3.Parallel 收集器Scavenge 是一个新生代的多线程收集器(并行收集器),它在回收期间不需要暂停其他用户线程,其采用的是Copying算法,该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量。
4.Parallel Old收集器 是Parallel Scavenge收集器的老年代版本(并行收集器),使用多线程和Mark-Compact算法。
5.CMS(Current Mark Sweep)收集器 是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法。
6.G1收集器 是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型。
1,串行收集器 -XX:+UseSerialGC:设置
2,并行收集器(吞吐量优先)
-XX:+UseParallelGC 选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。
-XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。
-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集。
3,并发收集器(响应时间优先)
-XX:+UseParNewGC 设置年轻代为并发收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。
CMS, 全称Concurrent Low Pause Collector,是jdk1.4后期版本开始引入的新gc算法,在jdk5和jdk6中得到了进一步改进,它的主要适合场景是对响应时间的重要性需求 大于对吞吐量的要求,能够承受垃圾回收线程和应用线程共享处理器资源,并且应用中存在比较多的长生命周期的对象的应用。CMS是用于对tenured generation的回收,也就是年老代的回收,目标是尽量减少应用的暂停时间,减少FullGC发生的几率,利用和应用程序线程并发的垃圾回收线程来 标记清除年老代。
-XX:+UseConcMarkSweepGC 设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了。所以,此时年轻代大小最好用-Xmn设置。
-verbose:gc:显示垃圾收集信息(在虚拟机发生内存回收时在输出设备显示信息)
UseConcMarkSweepGC 开启此参数使用ParNew & CMS(serial old为替补)搜集器
MaxTenuringThreshold:晋升老年代的最大年龄。默认为15,比如设为10,则对象在10次普通GC后将会被放入年老代。
-XX:+ExplicitGCInvokesConcurrent:System.gc()可以与应用程序并发执行。
GCTimeRatio:设置系统的吞吐量。比如设为99,则GC时间比为1/1+99=1%,也就是要求吞吐量为99%。若无法满足会缩小新生代大小。
CMSInitiatingOccupancyFraction 触发CMS收集器的内存比例。比如60%的意思就是说,当内存达到60%,就会开始进行CMS并发收集。
CMSFullGCsBeforeCompaction:设置在几次CMS垃圾收集后,触发一次内存整理。
-Xnoclassgc:禁用类垃圾回收,性能会高一点;
首先要知道 Stop the world的含义(网易面试):不管选择哪种GC算法,stop-the-world都是不可避免的。Stop-the-world意味着从应用中停下来并进入到GC执行过程中去。一旦Stop-the-world发生,除了GC所需的线程外,其他线程都将停止工作,中断了的线程直到GC任务结束才继续它们的任务。GC调优通常就是为了改善stop-the-world的时间
CMS收集器是一种以获取最短回收停顿时间为目标的收集器,CMS收集器是基于“”标记--清除”(Mark-Sweep)算法实现的,整个过程分为四个步骤:
1. 初始标记 (Stop the World事件 CPU停顿, 很短) 初始标记仅标记一下GC Roots能直接关联到的对象,速度很快;
2. 并发标记 (收集垃圾跟用户线程一起执行) 初始标记和重新标记任然需要“stop the world”,并发标记过程就是进行GC Roots Tracing的过程;
3. 重新标记 (Stop the World事件 CPU停顿,比初始标记稍微长,远比并发标记短)修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记时间短
4. 并发清理 -清除算法;
整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。