1.JVM参数选项
包括标准参数选项、-X参数选项、-XX参数选项
1.标准参数选项(了解)
1.-X开头比较稳定,后续版本基本不会变化,直接在DOS窗口中运行java或者java -help可以看到所有的标准选项。
2.比如:java -version
2.-X参数选项(了解)
1.非标准化参数,以-X开头,直接在DOS窗口中运行java -X命令可以看到所有的X选项。
2.JVM的JIT编译模式相关的选项(重点):
-Xint:只使用解释器:所有字节码都被解释执行,这个模式的速度是很慢的。
-Xcomp:只使用编译器:所有字节码第一次使用就被编译成本地代码,然后在执行。
-Xmixed:混合模式:这是默认模式,刚开始的时候使用解释器慢慢解释执行,后来让JIT即时编译器根据程序运行的情况,有选择地将某些热点代码提前编译并缓存在本地,在执行的时候效率就非常高了。
使用什么模式,在使用java -version时会显示。
3.特别的:-Xms<size>设置初始Java堆大小,等价于-XX:InitialHeapSize;
-Xmx<size>设置最大Java堆大小,等价于-XX:MaxHeapSize;
-Xss<size>设置Java线程堆栈大小,等价于-XX:ThreadStackSize。
2.-XX参数选项(重点)
1.非标准化参数,以-XX开头。
2.格式分为Boolean类型和key-value类型。
Boolean类型:-XX:+option表示启用option属性,-XX:-option表示禁用option属性。
比如:-XX:+PrintGCDetails 开启打印GC日志。-XX:-PrintGCDetails 关闭打印GC日志。
key-value类型:子类型1:数值型格式-XX:option=number。比如:-XX:SurvivorRatio=8。可带上参数,比如m、M标识兆,k、k表示kb.
子类型2:非数值型格式-XX:name=string。比如:-XX:HeapDumpPath=/usr/local/aa.hprof
3.特别的:java -XX:+PrintFlagsFinal,输出所有参数的名称和默认值
2.添加JVM参数选项
1.eclipse
Run As–> Run Configuration–>VM arguments处输入参数
2.idea
edit configuration –>VM OPTIONS处输入参数
3.运行jar包
java -Xms50m -Xmx50m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -jar demo.jar
4.通过Tomcat运行war包
1.Linux系统下可以在tomcat/bin/catalina.sh中添加类似如下配置:
JAVA_OPTS=”-Xms512M -Xmx1024M”
2.Windows系统下载catalina.bat中添加类似如下配置:
set “JAVA_OPTS=-Xms512M -Xmx1024M”
5.程序运行过程中
1.使用jinfo -flag name=value pid 设置非Boolean类型参数
2.使用jinfo -flag [+|-]name pid 设置Boolean类型参数
3.常用的JVM参数选项
1.打印设置的XX选项及值
-XX:+PrintCommandLineFlags 可以让程序运行前打印出用户手动设置或者JVM自动设置的XX选项。
-XX:+PrintFlagsInitial 表示打印出所有XX选项的默认值.
-XX:+PrintFlagsFinal 表示打印出XX选项在运行程序时生效的值,结果中的等于号前有冒号说明已被修改.
-XX:+PrintVMOptions 打印JVM的参数
2.堆、栈、方法区等内存大小设置
1.栈
-Xss128k 等价于-XX:ThreadStackSize,设置每个线程的栈大小为128k;
2.堆
-Xms350m 设置JVM初始堆内存为350M;
-Xmx350m 设置JVM最大堆内存为350M;
-Xmn2g 设置年轻代初始值和年轻代最大值都是2G,官方推荐配置为整个堆大小的3/8;
-XX:NewSize=1024m 设置年轻代初始值为1024M;
-XX:MaxNewSize=1024m 设置年轻代最大值为1024M;
-XX:SurvivorRatio=8 设置年轻代中Eden区与一个Survivor区的比值,默认为8;
-XX:+UseAdaptiveSizePolicy 自动选择各区大小比例,默认开启;
-XX:NewRatio=2 设置老年代与年轻代(包括1个Eden区和2个Survivor区)的比值,默认为2;
-XX:PretenureSizeThreadshold=1024 设置让大于此阈值的对象直接分配在老年代,单位为字节;
-XX:MaxTenuringThreshold=15 新生代每次MinorGC后,还存活的对象年龄+1,当对象的年龄大于设置的这个值时就进入老年代,默认15;
-XX:+PrintTenuringDistribution 让JVM在每次MinorGC后打印出当前使用的Survivor中对象的年龄分布;
-XX:TargetSurvivorRatio 表示MinorGC结束后Survivor区域中占用空间的期望比例
3.方法区
永久代:-XX:PermSize=256m 设置永久代初始值为256M;
-XX:MaxPermSize=256m 设置永久代最大值为256M;
元空间:-XX:MetaspaceSize 初始空间大小;
-XX:MaxMetaspaceSize 最大空间,默认没有限制;
-XX:+UseCompressedOops 使用压缩对象指针;
-XX:+UseCompressedClassPointers 使用压缩类指针
4.直接内存
-XX:MaxDirectMemorySize 指定DirectMemory容量,若未指定,则默认与Java堆最大值一样.
3.OutOfMemory相关的选项
-XX:+HeapDumpOnOutMemoryError 表示在内存出现OOM的时候,生成Heap转储文件,以便后续分析,-XX:+HeapDumpBeforeFullGC和-XX:+HeapDumpOnOutMemoryError只能设置1个。
-XX:+HeapDumpBeforeFullGC 表示在出现FullGC之前,生成Heap转储文件,以便后续分析,请注意FullGC可能出现多次,那么dump文件也会生成多个.
-XX:HeapDumpPath=path 指定heap转存文件的存储路径,如果不指定,就会将dump文件放在当前目录中.
-XX:OnOutOfMemoryError 指定一个可行性程序或者脚本的路径,当发生OOM的时候,去执行这个脚本
4.垃圾收集器相关的选项
1.查看默认的垃圾回收器
-XX:PrintCommandLineFlags和jinfo -flag 相关垃圾回收器参数 进程ID,这两个命令都可以。
2.Serial回收器
-XX:+UseSerialGC,等价于新生代使用Serial,老年代使用 Serial Old.
3.Parnew回收器
4.Parallel回收器
Parallel回收器主打吞吐量,而CMS和G1主打低延迟,如果主打吞吐量,那么就不应该限制最大停顿时间,
所以-XX:MaxGCPauseMills不应该设置.
-XX:MaxGCPauseMills中的调整堆大小通过默认开启的-XX:+UseAdaptiveSizePolicy来实现.
5.cms
6.G1
如果使用G1垃圾收集器,不建议设置-Xmn和-XX:NewRatio,毕竟可能影响G1的自动调节.
7.怎么选择垃圾收集器
1.优先调整堆的大小让JVM自适应完成。
2.如果内存小于100M,使用串行收集器。
3.如果单核、单机程序,并且没有停顿时间的要求,使用串行收集器。
4.如果是多CPU、需要搞吞吐量、允许停顿时间超过1秒,选择并行或JVM自行选择。
5.如果是多CPU、追求低停顿时间、需快速响应,使用并发收集器。官方推荐G1,现在的互联网项目基本都使用G1。
5.GC日志相关选项
-verbose:gc 输出日志信息,默认输出的标准输出.
-XX:+PrintGC 等同于-verbose:gc,表示打开简化的日志.
-XX:+PrintGCDetails 在发生垃圾回收时打印内存回收详细的日志,并在进程退出时输出当前内存各区域的分配情况.
-XX:+PrintGCTimeStamps 程序启动到GC发生的时间秒数,不可以独立使用,需要配合-XX:+PrintGCDetails使用.
-XX:+PrintGCDateStamps 输出GC发生时的时间戳(以日期的形式,例如:2013-05-04T21:53:59.234+0800),
不可以独立使用,可以配合-XX:+PrintGCDetails使用.
-XX:+PrintHeapAtGC 每一次GC前和GC后,都打印堆信息.
-XLoggc:file 把GC日志写入到一个文件中去,而不是打印到标准输出中.
-XX:GCLogFileSize=1M 控制GC日志文件的大小.
-XX:+UseGCLogFileRotation 启用GC日志文件的自动转储.
-XX:+PrintTenuringDistribution 让JVM在每次MinorGC后打印出当前使用的Survivor中对象的年龄分布.
4.GC日志格式
1.GC分类
1.新生代收集:当Eden区满的时候就会进行新生代收集,所以新生代收集和S0区域和S1区域无关.
2.老年代收集和新生代收集的关系:进行老年代收集之前会先进行一次年轻代的垃圾收集,原因如下:
一个比较大的对象无法放入新生代,那它自然会往老年代去放,如果老年代也放不下,那会先进行一次新生代的垃圾收集,
之后尝试往新生代放,如果还是放不下,才会进行老年代的垃圾收集,之后在往老年代去放,这是一个过程,
我来说明一下为什么需要往老年代放,但是放不下,而进行新生代垃圾收集的原因,这是因为新生代垃圾收集比老年代垃圾收集
更加简单,这样做可以节省性能.
3.进行垃圾收集的时候,堆包含新生代、老年代、元空间/永久代:可以看出Heap后面包含着新生代、老年代、元空间,
但是我们设置堆空间大小的时候设置的只是新生代、老年代而已,元空间是分开设置的.
4.哪些情况会触发Full GC:老年代空间不足、方法区空间不足、显示调用System.gc()、
Minior GC进入老年代的数据的平均大小 大于 老年代的可用内存、大对象直接进入老年代,而老年代的可用空间不足.
2.GC日志分类
MinorGC FullGC
3.GC日志结构剖析
1.垃圾收集器
2.GC前后情况
3.GC时间
4.注意
full GC日志中,在显示完区域容量GC的情况之后,会接着显示整个堆内存区域的GC情况:GC前堆内存已使用容量->GC后堆内存容量(堆内存总容量), 并且堆内存总容量 = 9/10 新生代 + 老年代,然后堆内存总容量肯定小于初始化的内存大小
5.GC日志分析工具
常见的有GCEasy、GCViewer、HPjmeter