1Trace 跟踪的参数

1).打印GC日志信息

-verbose:gc

-XX:+PrintGCDetails


[GC[DefNew: 4416K->0K(4928K), 0.0001897 secs] 4790K->374K(15872K), 0.0002232 secs]

java jvm设置打印jc日志 jvm设置参数打印gc日志_堆内存


2).GC日志文件目录

-Xloggc:d:/gc.log

指定GC log的位置,以文件输出

帮助开发人员分析问题3).打印堆信息(每一次GC后)

-XX:+PrintHeapAtGC

java jvm设置打印jc日志 jvm设置参数打印gc日志_java jvm设置打印jc日志_02


4).打印类加载信息

-XX:+TraceClassLoading

java jvm设置打印jc日志 jvm设置参数打印gc日志_堆内存_03

5)-XX:+PrintClassHistogram

按下Ctrl+Break后,打印类的信息:

分别显示:序号、实例数量、总大小、类型

java jvm设置打印jc日志 jvm设置参数打印gc日志_内存区域_04

2 堆分配参数

1).-Xms 最小堆内存
2).-Xmx 最大堆内存

在Xms 和 Xmx配置相同的时候,初始化堆内存就是最大内存
在Xms 和 Xmx配置不相同的时候,JVM会尽可能维持最小堆内存,当内存不足的时候,会重新分配增加部分内存
在调用GC后,gc回收了堆内存,使空闲的内存增加

实例对比

java jvm设置打印jc日志 jvm设置参数打印gc日志_java jvm设置打印jc日志_05


java jvm设置打印jc日志 jvm设置参数打印gc日志_老年代_06

java jvm设置打印jc日志 jvm设置参数打印gc日志_内存区域_07


java jvm设置打印jc日志 jvm设置参数打印gc日志_内存区域_08

java jvm设置打印jc日志 jvm设置参数打印gc日志_java jvm设置打印jc日志_09


java jvm设置打印jc日志 jvm设置参数打印gc日志_java jvm设置打印jc日志_10

java jvm设置打印jc日志 jvm设置参数打印gc日志_内存区域_11


java jvm设置打印jc日志 jvm设置参数打印gc日志_老年代_12

3)–Xmn 设置年轻代大小

4)-XX:SurvivorRatio : Survivor(from和to)和eden的比例值
默认为8,survivor:eden=2:8 , from survivor占年轻代的1/10

5)-XX:NewRatio: 年轻代和老年代(不包含永久区)的比值
默认值为4,表示年轻代:老年代=1:4,也就是说年轻代占堆 的1/5

官方推荐
年轻代占堆的3/8;幸存区(from和to)占年轻代1/10

6)-XX:+HeapDumpOnOutOfMemoryError
OOM时导出堆到文件

7)-XX:+HeapDumpPath
导出OOM的路径

java jvm设置打印jc日志 jvm设置参数打印gc日志_java jvm设置打印jc日志_13


java jvm设置打印jc日志 jvm设置参数打印gc日志_老年代_14

总结
根据实际事情调整新生代和幸存代的大小
官方推荐新生代占堆的3/8
幸存代占新生代的1/10
在OOM时,记得Dump出堆,确保可以排查现场问题

3 GC日志解读及部分配置实例

[GC [PSYoungGen: 793K->600K(13824K)] 793K->600K(20992K), 0.0263516 secs] [Times: user=0.02 sys=0.00, real=0.03 secs]

1.[GC|Full GC, 当发生FullGC 时,jvm所有工作线程会暂停,直到Full GC完毕
2.[PSYoungGen: 垃圾回收的区域,这里是年轻代,PS(Prallel Scavenge)
3. 793K->600K(13824K) : 793K-GC之前 该内存区域(年轻代)已使用的空间 ->600k -GC之后 该内存区域(年轻代)已使用的空间(13824K:该内存区域总的容量)

  1. 793K->600K(20992K):GC之前堆已使用的容量-> GC之后堆已使用的容量(总的堆容量)
  2. 0.0263516 secs : gc的时间

java jvm设置打印jc日志 jvm设置参数打印gc日志_java jvm设置打印jc日志_15

java jvm设置打印jc日志 jvm设置参数打印gc日志_内存区域_16

java jvm设置打印jc日志 jvm设置参数打印gc日志_堆内存_17

java jvm设置打印jc日志 jvm设置参数打印gc日志_堆内存_18

java jvm设置打印jc日志 jvm设置参数打印gc日志_堆内存_19

java jvm设置打印jc日志 jvm设置参数打印gc日志_堆内存_20

4 永久区(方法区)及栈的参数配置
1)永久区
-XX:PermSize
初始化空间
-XX:MaxPermSize
最大空间

打开堆的Dump
堆空间实际占用非常少
但是永久区溢出 一样抛出OOM
如果堆空间没有用完也抛出了OOM,有可能是永久区导致的

2)栈
-Xss
每个线程都有独立的栈空间,保存方法中的局部变量,参数等

通常只有几百K
决定了函数调用的深度
每个线程都有独立的栈空间
局部变量、参数 分配在栈上

5 栈溢出实例

java jvm设置打印jc日志 jvm设置参数打印gc日志_老年代_21

6 常用的GC算法及其优缺点?
GC主要回收:堆空间和方法区

GC算法:
a)标记-清除算法:
标记:标记依然还在被引用的对象,也就是还存活的对象
清除:清除所有没有标记的对象
缺点:会生产内存碎片,以至于分配大对象的时候没有连续的空间来分配,导致 gc发生。

b)复制算法:把内存分为大小相等的两块,只使用其中一块空间,当这块空间用完的时候,就会发生gc,然后把依然存活的对象复制到另外一块空间中,然后把已使用过的内存空间一次清理掉

优点:相对标记清除算法,复制算法更加高效,而且不会产生空间碎片
缺点:内存利用率底
不适用的场景:老年代,发生gc后依次存活比较多的对象

c)标记-整理算法
1.标记过程,与标记清除算法一致
2.整理(压缩);会把依然存活的对象移动到内存的一段
3.清除:清除2步中内存之外的所有空间

d)分代收集算法
新生代:使用复制算法比较合适,因为新生代中的最新存活的几率很小
老年代:使用标记整理算法或者标记清除算法

7 GC判断对象是否"存活"或"死去"(GC回收的对象)
1.引用计数器算法

给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值加1;当引用失效时,计数器的值减;当该对象的计数器的值为0时,标志该对象失效。

2.跟搜索算法

基本思路:通过一系列的名为“GCRoots”的对象作为起始点,从这些节点开始向下搜索,搜索过的路径称为引用链,当一个对象到GCRoots没有任何引用链相连(用图论的话来说就是从GC Roots到这个对象不可达)时,则证明对象是不可用的。

8 stop-the-world
Stop-The-World
Java中一种全局暂停的现象
全局停顿,所有Java代码停止,native代码可以执行,但不能和JVM交互
多半由于GC引起
Dump线程
死锁检查
堆Dump

GC时为什么会有全局停顿?
类比在聚会时打扫房间,聚会时很乱,又有新的垃圾产生,房间永远打扫不干净,只 有让大家停止活动了,才能将房间打扫干净。

危害
长时间服务停止,没有响应
遇到HA系统,可能引起主备切换,严重危害生产环境。