JVM 学习笔记 (六)
前言:
前几篇文章和大家介绍了JVM中的内存模型以及垃圾回收器,今天和大家一起学习一下在平时jvm调优的过程中常用的参数以及命令。
JVM中-XX类型的参数:
我们经常用到的-XX类型有两种定义:
1. a.Boolean类型
格式: -XX:[+-]<name> +或-表示启用或者禁用name属性
比如: -XX:+UseConcMarkSweepGC 表示启用CMS类型的垃圾回收器
-XX:+UseG1GC 表示启用G1类型的垃圾回收器
2. b.非Boolean类型
格式: -XX<name>=<value>表示name属性的值是value
比如: -XX:MaxGCPauseMillis=500
还有一些常用的参数赋值方式,比如:
-Xms1000等价于-XX:InitialHeapSize=500 (设置JVM初始化时堆内存大小)
-Xmx1000等价于-XX:MaxHeapSize=1000 (设置JVM最大堆内存大小)
-Xss100等价于-XX:ThreadStackSize=100 (设置jvm中每个线程内存大小)
设置JVM参数的方式
-
开发工具中设置比如IDEA,eclipse
-
运行jar包的时候:java -XX:+UseG1GC xxx.jar
-
web容器比如tomcat,可以在脚本中的进行设置
-
通过jinfo实时调整某个java进程的参数(参数只有被标记为manageable的?ags可以被实时修改)
这里不详细展开讨论。
下图是网友整理好的JVM常用参数,分享给大家:
常用命令:
- jps
查看java进程
- jinfo
实时查看和调整JVM配置参数。例如: jinfo -flag name PID 查看某个java进程的name属性的值。
jinfo -flag MaxHeapSize PID
jinfo -flag UseG1GC PID
- jstat
查看虚拟机性能统计信息,比如查看类装载信息:jstat -class PID 1000 10 查看某个java进程的类装载信息,每1000毫秒输出一次,共输出10次。
- jstack
查看线程堆栈信息,比如: jstack PID。
这里值得说明的是,我们可以用这个命令来排查项目中的一些死锁情况,下面就模拟死锁场景:
代码如下:
//定义锁对象 class MyLock { public static Object obj1 = new Object(); public static Object obj2 = new Object(); } //死锁代码 class DeadLock implements Runnable { private boolean flag; DeadLock(boolean flag) { this.flag = flag; } public void run() { if (flag) { while (true) { synchronized (MyLock.obj1) { System.out.println(Thread.currentThread().getName() + "----if 获得obj1锁"); synchronized (MyLock.obj2) { System.out.println(Thread.currentThread().getName() + "--- -if获得obj2锁"); } } } } else { while (true) { synchronized (MyLock.obj2) { System.out.println(Thread.currentThread().getName() + "----否则 获得obj2锁"); synchronized (MyLock.obj1) { System.out.println(Thread.currentThread().getName() + "--- -否则获得obj1锁"); } } } } } }
运行结果如下:
去看看该进程的堆栈信息:
这里的信息可以看出两个线程都在等对方解锁对象,导致线程死锁。
- jmap
打印出堆内存相关信息: jmap -heap PID
dump出堆内存相关信息: jmap -dump:format=b,fifile=heap.hprof PID
如何设置当发生堆内存溢出的时候,能自动dump出该文件呢,这样便可以进行快速定位:
一般在开发中,JVM参数可以加上下面两句,这样内存溢出时,会自动dump出该文件
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof