JVM随堂笔记

JVM参数类型
1. 标准参数 -help, -version 稳定参数,在各个JDK版本中,基本不会变化
2. X参数 非标准化,在各JVM版本中可能会发生变化, 例如 -Xint 解释执行 -Xcomp 第一次使用就编译成本地代码 -Xmixed 混合模式, JVM自己来决定什么时候编译
3. XX参数 非标准化,相对不稳定,主要用于JVM调优和调整GC参数.
boolean类型: -XX:[+-]<name>表示启用或禁用某些功能,+号表示启用某功能, -表示禁用某功能
非boolean类型: -XX:<name>=<value> 表示name属性的值为value, 例 -XX:MaxGCPauseMillis=500

-Xmx -Xms 不是X参数, 而是XX参数 -Xms等价于 -XX:InitialHeapSize -Xmx等价于-XX:MaxHeapSize
-Xss 等价于 -XX:ThreadStackSize

查看JVM运行时参数
-XX:+PrintFlagsInitial 查看初始运行参数
-XX:+PrintFlagsFinal 查看最终参数
-XX:+UnlockExperimentalVMOptions 解锁实验参数.
-XX:+UnlockDiagosticVMOptions 解锁诊断参数.
-XX:+PrintCommandLineFlags 打印命令行参数

# java -XX:+PrintFlagsFinal -version

jstat -gc 表示查看gc信息
jstat -gc PID 1000 3 查看指定PID的gc信息,每1000毫秒刷新一次,显示3次

S0C S0U 是S0的总量和使用量, C表示capacity容量, U表示used已使用的量, S survive
S1C S1U同上

S0 和 S1的空间是一样大的, 同一个时间点,只会使用一个区域, S0 + S1 +Eden = Young区
堆区 = Young区 + Old区

EC, EU: Eden区总量和使用量
MC, MU: Metaspace区总量和使用量

CCSC, CCSU: 压缩类空间总量和使用量, 对象指针64位下使用32位指针

YGC, YGCT: YoungGC的次数和时间
FGC, FGCT: FullGC的次数与时间
GCT: 总的GC时间

JVM内存结果分为两大块, 堆区和非堆区
堆区分为 Young区和Old区, Yound区又两块, Survive + Eden区, Survive又分为两块, S0 和 S1,两个大小是一样的,同一个时间点S0和S1只有一个启用
非堆区JDK8之后改名叫Metaspace区,是操作系统的独立内存,独立于JVM之外

如何导出内存映像文件
1. 发生内存溢出自动导出
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./

2. 使用jmap命令手动导出
jmap -dump:format-b,file=heap.hprof PID

CPU使用太多解决
首先使用top查看哪个JAVA进程占用的CPU最多 比如 7930
然后使用jstack 7930 > 7930.txt 把线程相关信息导出到txt文件
top -p 7930 -H 查看使用CPU最多的线程, 比如 8247线程
然后使用printf “%x” 8247转换成16进制, 2037 然后去导出的txt文件中查看2037的线程在做什么事情.

死锁的解决
jstat 23674 > 23674.txt
查看该文件最后,会发现 Found 1 deadlock

JVM 内存结构

运行时数据区分为方法区,虚拟机栈,本地方法区,程序计数器, 常量池

垃圾回收算法
思想: 枚举根节点,做可达性分析
常见根节点: 类加载器, Thread, 虚拟机栈的本地变量表,static成员, 常量引用,本地方法栈的变量等

对象优生在Eden区分配, 大对象直接进入老年代: -XX:+PretenureSizeThreshold
长期存活的对象进入老年代: -XX:+MaxTenuringThreshold -XX:+PrintTenuringDistribution -XX:+TargetSurvivorRatio

垃圾收集器
串行收集器Serial: Serial, Serial Old, 一般用于嵌入式设备
并行收集器parallel: Parallel Scavenge, Parallel Old, 吞吐量, 花在垃圾收集的时间和花在应用时间的占比 -XX:GCTimeRatio=n, 垃圾收集时间占 1/(1 + n)
并发收集器Concurrent: CMS, G1, 停顿时间, 垃圾收集器做垃圾回收中断应用执行的时间 -XX:MaxGCPauseMillis

开启串行收集器 -XX:+UseSerialGC -XX:+UseSerialOldGC
并行收集器, 吞吐量优先 -XX:+UseParallelGC, -XX:+UseParallelOldGC

并发收集器,响应时间优先收集器,
CMS: -XX:+UseConcMarkSweepGC -XX+UseParNewGC
G1: -XX:UseG1GC

垃圾收集器搭配, 不同的区,使用的垃圾收集器不同.

如何选择垃圾收集器
1. 优先调整堆的大小让服务器自己来选择
2. 如果内存小于100M, 使用串行收集器
3. 如果是单核,并且没有停顿时间的要求,串行或者JVM自己选
4. 如果允许停顿时间超过1秒,选择并行或者让JVM自己选
5. 如果响应时间最重要,并且不能超过1秒, 使用并发收集器

并行垃圾收集器可以自动调整内存大小以满足用户设定的时间, 优先满足最小响应时间参数,然后满足最大暂停时间要求.
使用 -XX:YoungGenerationSizeIncrement=X 用于设置Young区的增长大小
-XX:TenuredGenerationSizeIncrement=X 用于设置Old区的增长大小
-XX:AdaptiveSizeDecrementScaleFactor=X 用于设置减小内存大小

CMS相关参数
-XX:ConcGCThreads 并发的GC线程数
-XX:+UseCMSCompactAtFullCollection FullGC之后做内存压缩
-XX:CMSFullGCsBeforeCompaction 多少次FullGC之后压缩一次.
-XX:CMSInitiatingOccupancyFraction Old占有填满多少存活率的时候,触发FullGC
-XX:+UseCMSInitiatingOccupancyOnly 是否动态可调
-XX:+CMSScavengeBeforeRemark FullGC之前先做YGC
-XX:+CMSClassUnloadingEnable 启用回收Perm区

iCMS 增量CMS, 适用于单核或双核CPU

G1收集器
适用于大内存, 停顿时间较小, 内存大于6G时性能较好,是一个新生代和老生代收集器

年轻代大小, 避免使用 -Xmn, -XX:NewRatio等显示设置Young区大小, 会覆盖暂停时间目标
暂停时间目标水要太严苛,其吞吐量目标是90%的应用程序时间和10%的垃圾回收时间,太严苛会直接影响到吞吐量

是否需要切换到G1
50%以上的堆被存活对象占用
对象分配和晋升的速度变化非常大
垃圾回收时间特别长,超过了1秒.

打印GC日志
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX+PrintGCDataStamps -Xloggc:/tmp/gc.log -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution

Parallel GC 调优原则
1.除非确定, 否则不要设置最大堆内存
2.优先设置吞吐量目标
3.如果吞吐量目标达不到,调大最大内存,不能让OS使用Swap, 如果仍然达不到,降低目标
4.吞吐量能达到, 但是GC的时间太长,就设置停顿时间的目标

Post navigation

发表评论

电子邮件地址不会被公开。 必填项已用*标注