一、JVM组成

JVM 组成部分
类加载子系统: 使用Java语言编写.java Source Code文件,通过javac编译成.class Byte Code文件。class loader类加载器将所需所有类加载到内存,必要时将类实例化成实例
运行时数据区: 最消耗内存的空间,需要优化
执行引擎: 包括JIT (JustInTimeCompiler)即时编译器, GC垃圾回收器
本地方法接口: 将本地方法栈通过JNI(Java Native Interface)调用Native Method Libraries, 比如:C,C++库等,扩展Java功能,融合不同的编程语言为Java所用
JVM运行时数据区域由下面部分构成:
Method Area (线程共享):方法区是所有线程共享的内存空间,存放已加载的类信息(构造方法,接口定义),常量(final),静态变量(static), 运行时常量池等。但实例变量存放在堆内存中. 从JDK8开始此空间由永久代改名为元空间
heap (线程共享):堆在虚拟机启动时创建,存放创建的所有对象信息。如果对象无法申请到可用内存将抛出OOM异常.堆是靠GC垃圾回收器管理的,通过-Xmx -Xms 指定最大堆和最小堆空间大小
Java stack (线程私有):Java栈是每个线程会分配一个栈,存放java中8大基本数据类型,对象引用,
- 实例的本地变量,方法参数和返回值等,基于FILO()(First In Last Out),每个方法为一个栈帧
Program Counter Register (线程私有):PC寄存器就是一个指针,指向方法区中的方法字节码,每一个线程用于记录当前线程正在执行的字节码指令地址。由执行引擎读取下一条指令.因为线程需要 切换,当一个线程被切换回来需要执行的时候,知道执行到哪里了
Native Method stack (线程私有):本地方法栈为本地方法执行构建的内存空间,存放本地方法执行时的局部变量、操作数等。
所谓本地方法,使用native 关健字修饰的方法,比如:Thread.sleep方法. 简单的说是非Java实现的方法,例如操作系统的C编写的库提供的本地方法,Java调用这些本地方法接口执行。但是要注意, 本地方法应该避免直接编程使用,因为Java可能跨平台使用,如果用了Windows API,换到了Linux平台部署就有了问题
二、堆内存分代


Heap堆内存分为
年轻代Young:Young Generation
伊甸园区eden: 只有一个,刚刚创建的对象
幸存(存活)区Servivor Space:有2个幸存区,一个是from区,一个是to区。大小相等、地位相同、可互换。
from 指的是本次复制数据的源区
to 指的是本次复制数据的目标区
老年代Tenured:Old Generation, 长时间存活的对象
参数 | 说明 | 举例 |
-Xms | 设置应用程序初始使用的堆内存大小(年轻代 +老年代) | -Xms2g |
-Xmx | 设置应用程序能获得的最大堆内存 早期JVM不建议超过32G,内存管理效率下降 | -Xmx4g |
-XX:NewSize | 设置初始新生代大小 | -XX:NewSize=128m |
-XX:MaxNewSize | 设置最大新生代内存空间 | – XX:MaxNewSize=256m |
-Xmnsize | 同时设置-XX:NewSize 和 -XX:MaxNewSize,代替两者 | -Xmn1g |
-XX:NewRatio | 以比例方式设置新生代和老年代 | -XX:NewRatio=2 即:new:old=1:2 |
– XX:SurvivorRatio | 以比例方式设置eden和survivor(S0或S1) | -XX:SurvivorRatio=6 即:Eden:S0:S1=6:1:1 |
-Xss | 设置每个线程私有的栈空间大小,依据具体线程大小和数量 | -Xss256k |
三、垃圾回收器

- 新生代
- 新生代串行收集器Serial:单线程、独占式串行,采用复制算法,简单高效但会造成STW
新生代并行回收收集器PS(Parallel Scavenge):多线程并行、独占式,会产生STW, 使用复制算法关注调整吞吐量,此收集器关注点是达到一个可控制的吞吐量
新生代并行收集器ParNew:就是Serial 收集器的多线程版,将单线程的串行收集器变成了多线程并行、独占式,使用复制算法,相当于PS的改进版
- 老年代
老年代串行收集器Serial Old:Serial Old是Serial收集器的老年代版本,单线程、独占式串行,回收算法使用标记压缩
老年代并行回收收集器Parallel Old:多线程、独占式并行,回收算法使用标记压缩,关注调整吞吐量
- Parallel Old收集器是Parallel Scavenge 收集器的老年代版本,这个收集器是JDK1.6之后才开始提供,从HotSpot虚拟机的垃圾收集器的图中也可以看出,Parallel Scavenge 收集器无法与CMS收集器配合工作,因为一个是为了吞吐量,一个是为了客户体验(也就是暂停时间的缩短)此为默认的新老年代的垃圾回收器
CMS (Concurrent Mark Sweep并发标记清除算法) 收集器
四、JVM相关工具
$JAVA_HOME/bin下
命令 | 说明 |
jps | 查看所有jvm进程 |
jinfo | 查看进程的运行环境参数,主要是jvm命令行参数 |
jstat | 对jvm应用程序的资源和性能进行实时监控 |
jstack | 查看所有线程的运行状态 |
jmap | 查看jvm占用物理内存的状态 |
jhat | +UseParNew |
jconsole | 图形工具 |
jvisualvm | 图形工具 |
jstat -gc 14314 1000 10
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
12800.0 13312.0 5943.6 0.0 736768.0 393975.6 2174464.0 169471.5 104472.0 93626.6 11568.0 9563.4 620 6.709 4 0.577 7.286
12800.0 13312.0 5943.6 0.0 736768.0 393975.6 2174464.0 169471.5 104472.0 93626.6 11568.0 9563.4 620 6.709 4 0.577 7.286
12800.0 13312.0 5943.6 0.0 736768.0 393975.6 2174464.0 169471.5 104472.0 93626.6 11568.0 9563.4 620 6.709 4 0.577 7.286
- S0C:S0区容量
- YGC:新生代的垃圾回收次数
- YGCT:新生代垃圾回收消耗的时长;
- FGC:Full GC的次数
- FGCT:Full GC消耗的时长GCT:GC消耗的总时长
jstack [-l] <pid>
jstack -F [-m] [-l] <pid>
-l:long listings,会显示额外的锁信息,因此,发生死锁时常用此选项
-m:混合模式,既输出java堆栈信息,也输出C/C++堆栈信息
-F:当使用”jstack -l PID”无响应,可以使用-F强制输出信息
#先获得一个java进程PID,然后jinfo [root@tomcat ~]#jstack -l 21407 2020-02-15 13:49:56
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.241-b07 mixed mode):
"RMI TCP Connection(4)-10.0.0.101" #16 daemon prio=9 os_prio=0 tid=0x00007f279c29e800 nid=0x5753 runnable [0x00007f279b181000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
......
jmap [option] <pid>
jmap -heap <pid> #查看堆空间的详细信息:
jmap -histo[:live] <pid> #查看堆内存中的对象的数目: #live:只统计活动对象;
jmap -dump:<dump-options> <pid> # live, format=b , file=<file>
jmap -heap 14314
Attaching to process ID 14314, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.181-b13
using thread-local object allocation.
Parallel GC with 4 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 4294967296 (4096.0MB)
NewSize = 715653120 (682.5MB)
MaxNewSize = 1431306240 (1365.0MB)
OldSize = 1431830528 (1365.5MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.tools.jmap.JMap.runTool(JMap.java:201)
at sun.tools.jmap.JMap.main(JMap.java:130)
Caused by: java.lang.RuntimeException: unknown CollectedHeap type : class sun.jvm.hotspot.gc_interface.CollectedHeap
at sun.jvm.hotspot.tools.HeapSummary.run(HeapSummary.java:157)
at sun.jvm.hotspot.tools.Tool.startInternal(Tool.java:260)
at sun.jvm.hotspot.tools.Tool.start(Tool.java:223)
at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
at sun.jvm.hotspot.tools.HeapSummary.main(HeapSummary.java:50)
... 6 more