深入理解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个条件才能算是“无用的类”:

  1. 该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。
  2. 加载该类的ClassLoader已经被回收。
  3. 该类对应的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=,其中live子参数说明是否只dump出存活的对象
-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++的堆栈
posted @ 2020-02-28 21:04  my_flash  阅读(190)  评论(0)    收藏  举报