一、JVM运行时划分的区域
1.程序计数器
用于存放当前线程下一个执行命令的指针。
每个线程私有一个程序计数器。
2.虚拟机栈
和程序计数器一样,每个线程私有一个。
用来存放程序运行方法操作引用地址和对象引用地址,另外会有一个栈帧去指向这些操作数地址,通过这个模型来实现方法进入、退出、赋值、运算等操作的调用。
3.本地方法栈
4. 堆
用于存放对象,包括新生代区+老年区
5.方法区(可以当做是永久代)
用来存放类加载的信息,静态变量,final属性、方法、常量。
5.1 常量池
是方法区的一部分, 用于存放一些静态常量,例如 字符串 "ABC" ;
JVM的堆大小
堆大小 = 新生代 + 老年代
新生代与老年代 所占堆大小比例,默认为: 1:2,
即新生代区占 3分1,老年代占3分2。
可通过JVM参数 -Xms 和 -Xmx 进行设置堆的大小,
以及通过–XX:NewRatio来指定 新生代与老年代占的比例
新生代
新生代 = Eden区 + From Survivor区 + To Survivor区
三个区比例默认为:8:1:1
可以通过 –XX:SurvivorRatio 进行设置比例
所有java对象都是从Eden区出生的。
永久代
用来存放方法区的东西,例如
- 类的加载信息
- final修饰的属性、方法、常量
- 静态变量
可通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值。
二、官方文档资料
Hotspot JVM 官方详细参数:
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.htmlOracle JRockit JVM 与 Hotspot JVM 参数对照表:
https://docs.oracle.com/javase/10/jrockit-hotspot/command-line-options.htm#JRHMG129
三、JVM调试
调优实战篇
https://blog.csdn.net/renfufei/article/details/61924893查看JAVA进程:
jps -lm
参数 -l : 显示运行的jar名称
参数 -m 显示传递的参数
- 查看GC日志(打印GC日志信息)
启动JVM时增加参数:
-XX:-PrintGCDetails
- 查看一个java进程信息:
信息包括 环境变量,jvm 参数:
jinfo {pid}
- 查看java进程堆的情况
查看所有 存活和不存活的对象:
jmap -histo {pid}
只查看存活对象:
jmap -histo:live {pid}
查看堆使用情况:
jmap -heap {pid}
- 增加进程内存使用检测功能
增加jvm参数:
-Xprof
程序完成后会打印一堆 信息出来。
- JVM工具执行时报错
报错结果像这样的
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.InternalError: void* type hasn't been seen when parsing int*
at sun.jvm.hotspot.HotSpotTypeDataBase.recursiveCreateBasicPointerType(HotSpotTypeDataBase.java:721)
at sun.jvm.hotspot.HotSpotTypeDataBase.lookupType(HotSpotTypeDataBase.java:134)
at sun.jvm.hotspot.HotSpotTypeDataBase.lookupOrCreateClass(HotSpotTypeDataBase.java:631)
at sun.jvm.hotspot.HotSpotTypeDataBase.createType(HotSpotTypeDataBase.java:751)
at sun.jvm.hotspot.HotSpotTypeDataBase.readVMTypes(HotSpotTypeDataBase.java:195)
at sun.jvm.hotspot.HotSpotTypeDataBase.<init>(HotSpotTypeDataBase.java:89)
at sun.jvm.hotspot.HotSpotAgent.setupVM(HotSpotAgent.java:395)
at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:305)
at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140)
at sun.jvm.hotspot.tools.Tool.start(Tool.java:185)
at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
at sun.jvm.hotspot.tools.HeapSummary.main(HeapSummary.java:49)
主要是因为当前用的JVM 工具版本跟运行JVM的版本不一致导致的,例如当前JDK是1.8,JVM工具用的自然也是1.8, 但运行的java程序缺失1.7,那就会包这个错误,貌似是1.8的JVM工具不兼容低版本的。