目录
server clint
1. -server
- 堆初始的空间大一些
- 并行垃圾回收器
- 启动慢,运行快
2. -clint
- 堆初始空间小一些
- 串行垃圾回收器
- 启动快,运行慢
32位操作系统
如果是Windows系统,不论硬件配置如何,都默认使用Client类型的JVM。
如果是其他操作系统上,机器配置有2GB以上的内存同时有2个以上CPU的话默认使用server模式,否则使用client模式。
64位操作系统
只有server类型,不支持client类型。
java ‐server ‐showversion TestJVM
java ‐client ‐showversion TestJVM
jvm参数
1. 标准参数 java -help
2. 非标准参数 java -X
3. -XX 非标准参数
- boolean类型 如:-XX:+DisableExplicitGC 表示禁用手动调用gc操作,程序中调用System.gc()无效 , + 表示true , - 表示false
非 boolean类型 如: -XX:NewRatio=1 表示新生代和老年代的比值
运行模式
1. -Xint 解释模式(interpreted mode),-Xint标记会强制JVM执行所有的字节码,会降低运行速度,通常低10倍或更多
2. -Xcomp 它与(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化,然而,很多应用在使用-Xcomp也会有一些性能损失,当然这比使用-Xint损失的 少,原因是-xcomp没有让JVM启用JIT编译器的全部功能。JIT编译器可以对是否需要编译做判断,如果所有代码都进行编译的话,对于一些只执行一次的代码就 没有意义了。
3. -Xmixed 混合模式,将解释模式与编译模式进行混合使用,由jvm自己决定,这是jvm默认的模式,也是推荐使用的模式
java ‐showversion ‐Xcomp TestJVM
jvm参数
jvm启动时参数
java -XX:+PrintFlagsFinal -version
jvm运行时参数
# 查看进程
ps -ef | grep JavaName
或者
jps
或者(查看运行的jar包是哪一个)
jsp -l
# 查看pid 运行时的 全部 参数
jinfo -flags 27540
# 查看pid 运行时指定的某个参数
jinfo -flag MaxNewSize 27540
# 查看 class 加载统计
jstat -class 27540
# Loaded:加载class的数量
# Bytes:所占用空间大小
# Unloaded:未加载数量
# Bytes:未加载占用空间
# Time:时间
# 查看 编译 统计
jstat -compiler 27540
# Compiled:编译数量。
# Failed:失败数量
# Invalid:不可用数量
# Time:时间
# FailedType:失败类型
# FailedMethod:失败的方法
# 查看 垃圾回收 统计
jstat -gc 27540
jstat -gc 27540 1000 10 # 每一秒打印一次,打印10次
# S0C:第一个Survivor区的大小(KB)
# S1C:第二个Survivor区的大小(KB)
# S0U:第一个Survivor区的使用大小(KB)
# S1U:第二个Survivor区的使用大小(KB)
# EC:Eden区的大小(KB)
# EU:Eden区的使用大小(KB)
# OC:Old区大小(KB)
# OU:Old使用大小(KB)
# MC:方法区大小(KB)
# MU:方法区使用大小(KB)
# CCSC:压缩类空间大小(KB)
# CCSU:压缩类空间使用大小(KB)
# YGC:年轻代垃圾回收次数
# YGCT:年轻代垃圾回收消耗时间
# FGC:老年代垃圾回收次数
# FGCT:老年代垃圾回收消耗时间
# GCT:垃圾回收消耗总时间
jmap
内存的状态
jstat -gc 27540 1000 10
Attaching to process ID 27540, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 25.281-b09
using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration: # 堆内存配置信息
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 536870912 (512.0MB)
NewSize = 268435456 (256.0MB)
MaxNewSize = 268435456 (256.0MB)
OldSize = 268435456 (256.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 12582912 (12.0MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 4294901760 (4095.9375MB)
G1HeapRegionSize = 0 (0.0MB)
Heap Usage: # 堆内存使用情况
New Generation (Eden + 1 Survivor Space): # 年轻代
capacity = 241631232 (230.4375MB)
used = 125634920 (119.8147964477539MB)
free = 115996312 (110.6227035522461MB)
51.99448720271393% used
Eden Space: # 伊甸园区
capacity = 214827008 (204.875MB)
used = 114354752 (109.05718994140625MB)
free = 100472256 (95.81781005859375MB)
53.23108721972239% used
From Space: # service0
capacity = 26804224 (25.5625MB)
used = 11280168 (10.757606506347656MB)
free = 15524056 (14.804893493652344MB)
42.083546235100854% used
To Space: # service1
capacity = 26804224 (25.5625MB)
used = 0 (0.0MB)
free = 26804224 (25.5625MB)
0.0% used
tenured generation: # 老年代
capacity = 268435456 (256.0MB)
used = 36934400 (35.223388671875MB)
free = 231501056 (220.776611328125MB)
13.759136199951172% used
26001 interned Strings occupying 2875600 bytes.
查看进程对象
# 由于打印的内容非常的多,所以使用 more 进行查看
# 查看进程中 活跃的对象
jmap -histo:live 27540 | more
# 查看进程中所有的对象
jmap -histo 27540 | more
num #instances #bytes class name
----------------------------------------------
1: 78913 10117688 [C
2: 15136 5160168 [Ljava.lang.Object;
3: 6946 3449424 [I
4: 6668 2534704 [B
5: 77212 1235392 java.lang.String
6: 12776 1213704 java.lang.Class
7: 13539 1191432 java.lang.reflect.Method
8: 48812 1171488 java.util.concurrent.ConcurrentHashMap$Node
9: 246 953264 [Ljava.util.concurrent.ConcurrentHashMap$Nod
e;
10: 10772 829848 [Ljava.util.HashMap$Node;
#对象说明
B byte
C char
D double
F float
I int
J long
Z boolean
[ 数组,如[I表示int[]
[L+类名 其他对象
保存内存某一个时刻的信息(二进制文件)
注意: b,file 中间是一个 逗号
保存内存执行命令的时候的情况数据,二进制的形式保存到文件中
jmap -dump:format=b,file=E:/var/dump.bat 27540
项目启动时保存内存溢出时的二进制文件
‐Xms8m ‐Xmx8m ‐XX:+HeapDumpOnOutOfMemoryError
# 初始内存8M, 最大内存8M, 堆内存溢出的时候将堆内存信息dump到文件中
jhat 分析二进制文件
使用 jhat 工具对,保存的二进制文件进行分析,分析结果以简易的web页面展示 ,指定的访问的端口为 9999
jhat -port 9999 E:/var/dump.bat
在页面最下方存在一个 OQL 工具,可以使用 SQL 语句的形式查询一些内容
对象的值,等信息
mat 分析二进制文件
jstack
jstack 27540
当系统代码发生死锁等情况的时候,可以通过该命令进行查看 代码执行中出现的问题
jvisualvm
在命令行输入该命令,会打开 Java VisualVM 工具
jvisualvm
监控远程进程的时候,需要对远程的 服务器以及部署的服务做一些配置
‐Dcom.sun.management.jmxremote ‐Dcom.sun.management.jmxremote.port=9999 ‐Dcom.sun.management.jmxremote.authenticate=false ‐Dcom.sun.management.jmxremote.ssl=false
# ‐Dcom.sun.management.jmxremote :允许使用JMX远程管理
# ‐Dcom.sun.management.jmxremote.port=9999 :JMX远程连接端口
# ‐Dcom.sun.management.jmxremote.authenticate=false :不进行身份认证,任何用 户都可以连接
# ‐Dcom.sun.management.jmxremote.ssl=false : 不使用ssl
JVM垃圾回收机制
垃圾回收算法
1. 引用计数法
优点:
- 实时性较高,无需等到内存不够的时候,才开始回收,运行时根据对象的计数器是否 为0,就可以直接回收。
- 在垃圾回收过程中,应用无需挂起。如果申请内存时,内存不足,则立刻报 outofmember 错误。
- 区域性,更新对象的计数器时,只是影响到该对象,不会扫描全部对象。
缺点:
每次对象被引用时,都需要去更新计数器,有一点时间开销。 浪费CPU资源,即使内存够用,仍然在运行时进行计数器的统计。 无法解决循环引用问题。(最大的缺点)
循环引用
2. 标记清除法
标记:从根节点开始标记引用的对象。
清除:未被标记引用的对象就是垃圾对象,可以被清理。
优点:
- 解决循环引用的问题
缺点:
- 效率较低,标记和清除两个动作都需要遍历所有的对象,并且在GC时,需要停止应用程序,对于交互性要求比较高的应用而言这个体验是非常差的。
- 通过标记清除算法清理出来的内存,碎片化较为严重,因为被回收的对象可能存在于 内存的各个角落,所以清理出来的内存是不连贯的。
3. 标记压缩算法
优点:
- 解决标记清除算法 碎片化 问题
缺点:
标记压缩算法多了一步,对象移动内存位置的步骤,其效率也有有一定的影响
4. 复制算法
优点:
在垃圾对象多的情况下,效率较高 清理后,内存无碎片缺点:
- 在垃圾对象少的情况下,不适用,如:老年代内存
- 分配的2块内存空间,在同一个时刻,只能使用一半,内存使用率较低
5. 分代算法
垃圾收集器与内存分配
串行垃圾收集器
‐XX:+UseSerialGC ‐XX:+PrintGCDetails
# UseSerialGC 指定年轻代和老年代都使用串行垃圾收集器
# PrintGCDetails 打印垃圾回收的详细信息
[GC (Allocation Failure) [DefNew: 4416K‐>512K(4928K), 0.0046102 secs] 4416K‐>1973K(15872K), 0.0046533 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [Tenured: 10944K‐>3107K(10944K), 0.0085637 secs] 15871K‐>3107K(15872K), [Metaspace: 3496K‐>3496K(1056768K)], 0.0085974 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
DefNew
表示使用的是串行垃圾收集器。
4416K->512K(4928K)
表示,年轻代GC前,占有4416K内存,GC后,占有512K内存,总大小4928K0.0046102 secs
表示,GC所用的时间,单位为毫秒。4416K->1973K(15872K)
表示,GC前,堆内存占有4416K,GC后,占有1973K,总大小为15872KFull GC
表示,内存空间全部进行GC
并行垃圾收集器
并行方式1:
-XX:+UseParNewGC 年轻代使用parNew 回收器,老年代使用串行收集器
[GC (Allocation Failure) [ParNew: 4416K‐>512K(4928K), 0.0032106 secs] 4416K‐>1988K(15872K), 0.0032697 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
# ParNew 表示使用的是 ParNew 垃圾收集器
并行方式2:
-XX:+UseParallelGC 年轻代使用ParallelGC垃圾回收器
-XX:+UseParallelOldGC 老年代使用ParallelOldGC垃圾回收器
-XX:MaxGCPauseMillis 设置最大的垃圾收集时的停顿时间,单位为毫秒,需要注意的时,ParallelGC为了达到设置的停顿时间,可能会调整堆大小或其他的参数,如果堆的大小设置的较小,就会导致GC工作变得很频繁,反而可能会影响到性能。
-XX:GCTimeRatio 设置垃圾回收时间占程序运行时间的百分比,公式为1/(1+n)。 它的值为0~100之间的数字,默认值为99,也就是垃圾回收时间不能超过1%
-XX:UseAdaptiveSizePolicy 自适应GC模式,垃圾回收器将自动调整年轻代、老年代等参数,达到吞吐量、堆大小、停顿时间之间的平衡。 一般用于,手动调整参数比较困难的场景,让收集器自动进行调整。
[GC (Allocation Failure) [PSYoungGen: 4096K‐>480K(4608K)] 4096K‐ >1840K(15872K), 0.0034307 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 505K‐>0K(4608K)] [ParOldGen: 10332K‐ >10751K(11264K)] 10837K‐>10751K(15872K), [Metaspace: 3491K‐ >3491K(1056768K)], 0.0793622 secs] [Times: user=0.13 sys=0.00, real=0.08 secs]
# PSYoungGen 表示使用的是,并行的垃圾收集器
CMS垃圾收集器
- 初始化标记(CMS-initial-mark) ,标记root,会导致stw;
- 并发标记(CMS-concurrent-mark),与用户线程同时运行;
- 预清理(CMS-concurrent-preclean),与用户线程同时运行;
- 重新标记(CMS-remark) ,会导致stw;
- 并发清除(CMS-concurrent-sweep),与用户线程同时运行;
- 调整堆大小,设置CMS在清理之后进行内存压缩,目的是清理内存中的碎片;
- 并发重置状态等待下次CMS的触发(CMS-concurrent-reset),与用户线程同时运行;
‐XX:+UseConcMarkSweepGC
# 设置 CMS 垃圾收集方式
#运行日志
[GC (Allocation Failure) [ParNew: 4926K‐>512K(4928K), 0.0041843 secs] 9424K‐>6736K(15872K), 0.0042168 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
#第一步,初始标记
[GC (CMS Initial Mark) [1 CMS‐initial‐mark: 6224K(10944K)] 6824K(15872K), 0.0004209 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
#第二步,并发标记
[CMS‐concurrent‐mark‐start] [CMS‐concurrent‐mark: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
#第三步,预处理
[CMS‐concurrent‐preclean‐start] [CMS‐concurrent‐preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
#第四步,重新标记
[GC (CMS Final Remark) [YG occupancy: 1657 K (4928 K)][Rescan (parallel) , 0.0005811 secs][weak refs processing, 0.0000136 secs][class unloading, 0.0003671 secs][scrub symbol table, 0.0006813 secs][scrub string table, 0.0001216 secs][1 CMS‐remark: 6224K(10944K)] 7881K(15872K), 0.0018324 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
#第五步,并发清理
[CMS‐concurrent‐sweep‐start] [CMS‐concurrent‐sweep: 0.004/0.004 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
#第六步,重置
[CMS‐concurrent‐reset‐start] [CMS‐concurrent‐reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
CMS 是英文 Concurrent Mark-Sweep 的简称,是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。在启动 JVM 的参数加上“-XX:+UseConcMarkSweepGC”来指定使用 CMS 垃圾回收器。
CMS 使用的是标记压缩的算法实现的,当剩余内存不能满足程序运行要求时,系统将会出现 Concurrent Mode Failure,临时 CMS 会采用 Serial Old(串行垃圾收集器) 回收器进行垃圾清除,此时的性能将会被降低。(其他博客看到的不知道是不是这样)
G1垃圾收集器
- 第一步,开启G1垃圾收集器
- 第二步,设置堆的最大内存
- 第三步,设置最大的停顿时间
G1中提供了三种模式垃圾回收模式:
- Young GC 年轻代GC
- Mixed GC 混合GC
- Full GC 堆内存的全量GC
-XX:+UseG1GC 使用 G1 垃圾收集器
-XX:MaxGCPauseMillis 设置期望达到的最大GC停顿时间指标(JVM会尽力实现,但不保证达到),默认值是 200 毫秒。
-XX:G1HeapRegionSize=n 设置的 G1 区域的大小。值是 2 的幂,范围是 1 MB 到 32 MB 之间。目标是根 据最小的 Java 堆大小划分出约 2048 个区域。 默认是堆内存的1/2000。
-XX:ParallelGCThreads=n 设置 STW 工作线程数的值。将 n 的值设置为逻辑处理器的数量。n 的值与逻辑处理器(CPU内核)的数量相同,最多为 8。
-XX:ConcGCThreads=n 设置并行标记的线程数。将 n 设置为并行垃圾回收线程数 (ParallelGCThreads) 的 1/4 左右。
-XX:InitiatingHeapOccupancyPercent=n 设置触发标记周期的 Java 堆占用率阈值。默认占用率是整个 Java 堆的 45%
注意:
年轻代大小
- 避免使用 -Xmn 选项或 -XX:NewRatio等其他相关选项显式设置年轻代大小。
- 固定年轻代的大小会覆盖暂停时间目标。 -XX:MaxGCPauseMillis
暂停时间目标不要太过严苛
- G1 GC 的吞吐量目标是 90% 的应用程序时间和 10%的垃圾回收时间。
- 评估 G1 GC 的吞吐量时,暂停时间目标不要太严苛。目标太过严苛表示您愿意承受更多的垃圾回收开销,而这会直接影响到吞吐量。
Remembered Set 区域
1. YangGC
- Eden空间的数据移动到Survivor空间中,如果Survivor空间不够,Eden空间的部分数据会直接晋升到年老代空间。
- Survivor区的数据移动到新的Survivor区中,也有部分数据晋升到老年代空间中。
- 最终Eden空间的数据为空,GC停止工作,应用线程继续执行
2. MixedGC
-XX:InitiatingHeapOccupancyPercent=n
# 默认:45%
# 该参数的意思是:当老年代大小占整个堆大小百分比达到该阀值时触发,MixedGC
MixedGC过程
1. 全局并发标记( global concurrent marking )
- 初始标记(initial mark,STW) 标记从根节点直接可达的对象,这个阶段会执行一次年轻代GC,会产生全局停顿
- 根区域扫描(root region scan) 在初始标记的存活区扫描对老年代的引用,并标记被引用的对象,该阶段与应用程序(非 STW)同时运行,并且只有完成该阶段后,才能开始下一次 STW 年轻代垃圾回收
- 并发标记(Concurrent Marking) 在整个堆中查找可访问的(存活的)对象。该阶段与应用程序同时运行,可以被 STW 年轻代垃圾回收中断
重新标记( Remark , STW ) 该阶段是 STW 回收,因为程序在运行,针对上一次的标记进行修正。- 清除垃圾(Cleanup,STW) 清点和重置标记状态,该阶段会STW,这个阶段并不会实际上去做垃圾的收集,等待evacuation阶段来回收
2. 拷贝存活对象( evacuation )
Evacuation 阶段是全暂停的。该阶段把一部分 Region 里的活对象拷贝到另一部分 Region中,从而实现垃圾的回收清理
3. Full GC
收集整个堆,包括young gen、old gen、perm gen(如果存在的话)等所有部分的模式。
GC日志输出参数
‐XX:+PrintGC 输出GC日志
‐XX:+PrintGCDetails 输出GC的详细日志
‐XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
‐XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013‐05‐ 04T21:53:59.234+0800)
‐XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
‐Xloggc:../logs/gc.log 日志文件的输出路径
可以将系统生成的文件,上传到 Universal JVM GC analyzer - Java Garbage collection log analysis made easy 进行GC日志文件的分析。
补充
GC方式的分为两大类:
1. Partial GC:并不收集整个GC堆的模式
- Young GC:只收集young gen的GC
- Old GC:只收集old gen的GC。只有CMS的concurrent collection是这个模式
- Mixed GC:收集整个young gen以及部分old gen的GC。只有G1有这个模式
2. Full GC:收集整个堆,包括young gen、old gen、perm gen(如果存在的话)等所有部分的模式。