深入理解Java虚拟机 JVM高级特性与最佳实践 笔记20170410
目录
常用JVM配置参数
-XX:+ DisableExplicitGC来禁止RMI调用System.gc
Trace跟踪参数
-verbose:gc
-XX:+printGC
-XX:+PrintGCDetails //打印GC详细信息
//只要设置-XX:+PrintGCDetails 就会自动带上-verbose:gc和-XX:+PrintGC
-XX:+PrintGCDateStamps/-XX:+PrintGCTimeStamps 输出gc的触发时间
-Xloggc:/path/gc.log
-XX:+UseGCLogFileRotation 启用GC日志文件的自动转储 (Since Java)
-XX:NumberOfGClogFiles=1 GC日志文件的循环数目 (Since Java)
-XX:GCLogFileSize=1M 控制GC日志文件的大小 (Since Java)
-XX:+PrintGC包含-verbose:gc
-XX:+PrintGCDetails //包含-XX:+PrintGC
堆的分配参数
栈的分配参数
2.3.2 对象的内存布局
在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
表2-1 HotSpot虚拟机的对象头
| 存储内容 | 标志位 | 状态 |
|---|---|---|
| 对象哈希码,对象的分代年龄 | 01 | 状态 |
| 指向锁记录的指针 | 00 | 轻量级锁定 |
| 指向重量级锁的指针 | 10 | 膨胀(重量级锁定) |
| 空,不需要记录信息 | 11 | GC标记 |
| 偏向线程ID | 01 | 可偏向 |
2.4.1 Java堆溢出
将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展),通过参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析
VM Args:-Xms20m-Xmx20m-XX:+HeapDumpOnOutOfMemoryError
2.4.2 虚拟机栈和本地方法栈溢出
由于在HotSpot虚拟机中并不区分虚拟机栈和本地方法栈,因此,对于HotSpot来说,虽然-Xoss参数(设置本地方法栈大小)存在,但实际上是无效的,栈容量只由-Xss参数设定
VM Args:-Xss128k
2.4.3 方法区和运行时常量池溢出
在JDK 1.6及之前的版本中,由于常量池分配在永久代内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区大小,从而间接限制其中常量池的容量
2.4.4 本机直接内存溢出
DirectMemory容量可通过-XX:MaxDirectMemorySize指定,如果不指定,则默认与Java堆最大值(-Xmx指定)一样
VM Args:-Xmx20M -XX:MaxDirectMemorySize=10M
虽然使用DirectByteBuffer分配内存也会抛出内存溢出异常,但它抛出异常时并没有真正向操作系统申请分配内存,而是通过计算得知内存无法分配,于是手动抛出异常,真正申请分配内存的方法是unsafe.allocateMemory()
3.2.3 再谈引用
Java对引用的概念进行了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4种,这4种引用强度依次逐渐减弱
3.2.5 生存还是死亡
一个对象的finalize()方法最多只会被系统自动调用一次
3.2.5 回收方法区
类需要同时满足下面3个条件才能算是“无用的类”:
- 该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。
- 加载该类的ClassLoader已经被回收。
- 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
虚拟机可以对满足上述3个条件的无用类进行回收,这里说的仅仅是“可以”,而并不是和对象一样,不使用了就必然会回收。是否对类进行回收,HotSpot虚拟机提供了 -Xnoclassgc 参数进行控制,还可以使用** -verbose:class 以及 -XX:+TraceClassLoading 、 -XX:+TraceClassUnLoading **查看类加载和卸载信息,其中-verbose:class和-XX:+TraceClassLoading可以在Product版的虚拟机中使用,-XX:+TraceClassUnLoading参数需要FastDebug版的虚拟机支持。
3.5.9 垃圾回收器参数总结
表3-2 8 垃圾收集相关的常用参数
|参数|描述|
|:----------|:----------|
|UseSerialGC|虚拟机运行在Client模式下的默认值,打开此开关后,使用Serial+Serial Old 的收集器组合进行内存回收|
|UserParNewGC|打开此开关后,使用ParNew + Serial Old 的收集器组合进行内存回收|
|UserConcMarkSweepGC| 打开此开关后,使用ParNew + CMS + Serial Old 的收集器组合进行内存回收。Serial Old收集器将作为CMS收集器出现Concurrent Mode Failure失败后的后备收集器使用|
|UseParallelGC|虚拟机运行在Server模式下的默认值,打开此开关后,使用Parallel Scavenge + Serial Old(PS markSweep)的收集器组合进行内存回收。|
|UseParallelOldGC|打开此开关后,使用 Parallel Scavenge + Parallel Old的收集器组合进行内存回收|
|ServivorRatio|新生代中Eden区域与Survivor区域的容量比值,默认是8,代表 Eden:Survivor = 8:1|
|PretenureSizeThreshold|直接晋升到老年代的对象大小,设置这个参数后,大于这个参数的对象将直接在老年代分配, PretenureSizeThreshold参数只对Serial和ParNew两款收集器有效 ,Parallel Scavenge收集器不认识这个参数,Parallel Scavenge收集器一般并不需要设置。如果遇到必须使用此参数的场合,可以考虑ParNew加CMS的收集器组合 |
|MaxTenuringThreshold|晋升到老年代的对象年龄,每个对象在坚持过一次Minor GC之后,年龄就增加1,当超过这个参数值时,就进入老年代|
|UseAdaptiveSizePolicy|动态调整java堆中各个区域的大小以及进入老年代的年龄|
|HandlePromotionFailure|是否允许分配担保失败,即老年代的剩于空间不足以应付新生代的整个Eden和Survivor区的所有对象都存活的极端情况|
|ParallelGCThreads|设置并行GC时进行内存回收的线程数|
|GCTimeRatio|GC时间占总时间的比率,默认值是99,即允许1%的GC时间,仅在使用Parallel Scavenge 收集器时生效|
|MaxGCPauseMillis|设置GC的最大停顿时间,仅在使用ParaHel Scavenge 收集器时,生效|
|CMSInitiatingOccupancyFraction|设置CMS收集器在老年代空间被使用多少后触发垃圾收集。默认值为68%,仅在使用CMS收集器时生效|
|UseCMSCompactAtFullCollection|设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片整理。仅在使用CMS收集器时生效|
|CMSFullGCsBeforeCompaction|设置CMS收集器在进行若干次垃圾收集后再启动一次内存碎片整理。仅在使用CMS收集器时生效|
3.6.1 对象优先在Eden分配
/**
*VM参数:-verbose:gc-Xms20M-Xmx20M-Xmn10M-XX:+PrintGCDetails
-XX:SurvivorRatio=8
*/
3.6.2 大对象直接进入老年代
/**
*VM参数:-verbose:gc-Xms20M-Xmx20M-Xmn10M-XX:+PrintGCDetails-XX:SurvivorRatio=8
*-XX:PretenureSizeThreshold=3145728
*/
3.6.3 长期存活的对象将进入老年代
/**
*VM参数:-verbose:gc-Xms20M-Xmx20M-Xmn10M-XX:+PrintGCDetails-XX:SurvivorRatio=8-XX:MaxTenuringThreshold=1
*-XX:+PrintTenuringDistribution
*/
3.6.4 动态对象年龄判定
/**
*VM参数:-verbose:gc-Xms20M-Xmx20M-Xmn10M-XX:+PrintGCDetails-XX:SurvivorRatio=8-XX:MaxTenuringThreshold=15
*-XX:+PrintTenuringDistribution
*/
3.6.5 空间分配担保
/**
*VM参数:-Xms20M-Xmx20M-Xmn10M-XX:+PrintGCDetails-XX:SurvivorRatio=8-XX:-HandlePromotionFailure
*/
4.2 JDK的命令行工具
表 4-1 Sun JDK 监控和故障处理工具
| 名称 | 主要作用 |
|---|---|
| jps | JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程 |
| jstat | JVM Statistics Monitoring Tool,用于手机HotSpot虚拟机各方面的运行数据 |
| jinfo | Configuration Info for Java,显示虚拟机配置信息 |
| ---------- | ---------- |
|jmap|Memeory for Java,生成虚拟机的内存转储快照(heapdump文件)
|jhat|JVM Heap Dump Brower 用于分析headdump文件,他会建立一个HTTP/HTML服务器,让用户可以在浏览器上查看分析结果|
|jstack|Statck Trace for Java,显示虚拟机的线程快照|
表 4-2 jps工具主要选项
| 选项 | 作用 |
|---|---|
| -q | 只输出LVMID,省略主类的名称 |
| -m | 输出虚拟机进程启动时传递给主类main()函数的参数 |
| -l | 输出主类的全名,如果进程执行的是jar包,输出jar路径 |
| -v | 输出虚拟机进程启动时jvm参数 |
4.2.2 jstat:虚拟机统计信息监视工具
表 4-3 jstat 工具主要选项
| 选项 | 作用 |
|---|---|
| -class | 监视类装载、卸载数量、总空间以及类装载所耗费的时间 |
| -gc | 监视java堆状况,包括Eden区,两个Survivor区,老年代、永久代等的容量,已用空间、GC时间合计等信息 |
| -gccapacity | 监视内容与-gc基本相同,但输出主要关注java堆各个区域使用到的最大,最小空间 |
| -gcutil | 监视内容与-gc基本相同,但输出主要关注已使用空间与总空间的百分比 |
| -gccause | 与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因 |
| -gcnew | 监视新生代GC状况 |
| -gcnewcapacity | 监视内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间 |
| -gcold | 监视老年代GC状况 |
| -gcoldcapacity | 监视内容与 -gcold基本相同,输出主要关注使用到的 最大、最小空间 |
| -gcpermcapacity | 输出永久代使用到的的最大、最小空间 |
| -compiler | 输出JIT 编译器编译过的方法、耗时等信息 |
| -printcomplilation | 输出已经被JIT编译的方法 |
4.2.4 jmap:Java内存映像工具
| 选项 | 作用 |
|---|---|
| -dump | 生成java堆转储快照,格式为:-dump[live, ]fixmat=b,file= |
| -finalizerinfo | 显示为F-Queue中等待Finalizer线程执行finalize方法的对象。只在Linux/Solaris平台下有效 |
| -heap | 显示java堆详细信息,如使用哪种回收器,参数配置、分代状况等。只在Linux/Solaris平台下有效 |
| -histo | 显示堆中对象统计信息,包括类、实例数量、合计容量 |
| -permstat | 以ClassLoader为统计口径显示永久代内存状态。只在Linux/Solaris平台下有效 |
| -F | 当虚拟机进程堆-dump选项没有响应时,可使用这个选项强制生成dump快照。只在Linux/Solaris平台下有效 |
C:\Users\IcyFenix>jmap-dump:format=b,file=eclipse.bin 3500
Dumping heap to C:\Users\IcyFenix\eclipse.bin……
Heap dump file created
4.2.5 jhat:虚拟机堆转储快照分析工具
VisualVM,以及专业用于分析dump文件的Eclipse Memory Analyzer、IBM HeapAnalyzer 等工具
4.2.6 jstack:Java堆栈跟踪工具
| 选项 | 作用 |
|---|---|
| -F | 当正常输出的请求不被响应时,强制输出线程堆栈 |
| -l | 出堆栈外,显示关于锁的附加信息 |
| -m | 如果调用到本地方法的话,可以显示C/C++的堆栈 |

浙公网安备 33010602011771号