jvm常用参数与命令
- 常用jvm参数
-Xms20M 设置初始 Java 堆大小
-Xmx20M 设置最大 Java 堆大小
-XX:MaxDirectMemorySize=20M 设置堆外内存大小
-XX:MetaspaceSize=20m 设置初始元空间大小
-XX:MaxMetaspaceSize=20m 设置最大元空间大小
- jps命令
jps 查看所有jvm进程 (进程id 主类名)
jps -l 显示全类名
jps -v 显示jvm启动参数
jps -m 显示传递给main函数的参数
- jinfo id 实时查看虚拟机各项参数
- jmap命令 用于内存分析
jmap -dump:format=b,file=filename 进程id 将内存使用情况dump到文件中
jmap -heap 进程id 查看进程中堆内存的详细使用情况
- jstack命令 用户线程分析
jstack 进程id 输出当前jvm进程中每一个线程的执行方法的堆栈集合。
使用jmap查看堆内存信息
- jmap -heap 进程id 就会将当前Java进程中堆内存信息打印出来
- 堆内存配置信息如下,包含了堆内存空间大小,新生代,年老代内存大小等信息。
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 8388608 (8.0MB)
NewSize = 2621440 (2.5MB)
MaxNewSize = 2621440 (2.5MB)
OldSize = 5767168 (5.5MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
- 堆内存使用信息如下,包含每个区域使用情况,剩余空间,使用率等。
Heap Usage:
PS Young Generation
Eden Space:
capacity = 1572864 (1.5MB) //eden区大小
used = 1339624 (1.2775650024414062MB) //eden区使用内存
free = 233240 (0.22243499755859375MB) //eden区剩余内存
85.17100016276042% used //eden区使用率
From Space: //两个survivor区使用情况
capacity = 524288 (0.5MB)
used = 520240 (0.4961395263671875MB)
free = 4048 (0.0038604736328125MB)
99.2279052734375% used
To Space:
capacity = 524288 (0.5MB)
used = 0 (0.0MB)
free = 524288 (0.5MB)
0.0% used
PS Old Generation //年老代使用情况
capacity = 5767168 (5.5MB)
used = 3761512 (3.5872573852539062MB)
free = 2005656 (1.9127426147460938MB)
65.22286155007102% used
4790 interned Strings occupying 378432 bytes.
使用jmap检测堆内存溢出问题
- 如下代码会产生堆内存溢出问题
//设置堆内存大小为8m -Xmx8m
public class Test {
public static Logger log = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) throws InterruptedException {
LinkedList<String> list = new LinkedList<>();
String str = "hello";
int i = 0;
while(true){
System.out.println(i);
str = str + str;
i++;
list.add(str);
Thread.sleep(2000);
}
}
}
- 首先使用jps查看当前程序进程id
- 然后使用jmap id 就可以查看进程当前时刻的堆内存使用情况。如下可以发现新生代 老年代内存占有率都很高,已经达到濒临溢出。
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 8388608 (8.0MB)
NewSize = 2621440 (2.5MB)
MaxNewSize = 2621440 (2.5MB)
OldSize = 5767168 (5.5MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 1572864 (1.5MB)
used = 1339624 (1.2775650024414062MB)
free = 233240 (0.22243499755859375MB)
85.17100016276042% used
From Space:
capacity = 524288 (0.5MB)
used = 520240 (0.4961395263671875MB)
free = 4048 (0.0038604736328125MB)
99.2279052734375% used
To Space:
capacity = 524288 (0.5MB)
used = 0 (0.0MB)
free = 524288 (0.5MB)
0.0% used
PS Old Generation
capacity = 5767168 (5.5MB)
used = 3761512 (3.5872573852539062MB)
free = 2005656 (1.9127426147460938MB)
65.22286155007102% used
4790 interned Strings occupying 378432 bytes.
jstack
- 使用jstack检测线程死锁问题。
- 运行如下代码
public class Test {
static Object a = new Object();
static Object b = new Object();
public static Logger log = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) throws InterruptedException {
new Thread(()->{
synchronized (a){
sleep(1000);
synchronized (b){
}
}
},"t1").start();
new Thread(()->{
synchronized (b){
sleep(1000);
synchronized (a){
}
}
},"t2").start();
}
public static void sleep(int n) {
try {
Thread.sleep(n);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 使用jps查看当前运行程序的进程id
- 然后使用 jstack 进程id 就可以打印当前jvm进程中的线程信息
- 通过如下信息就可以判断出是t1线程和t2线程出现死锁。
Found one Java-level deadlock:
=============================
"t2":
waiting to lock monitor 0x000000001c940ee8 (object 0x000000076ba1d9c0, a java.lang.Object),
which is held by "t1"
"t1":
waiting to lock monitor 0x000000001c9431f8 (object 0x000000076ba1d9d0, a java.lang.Object),
which is held by "t2"
Java stack information for the threads listed above:
===================================================
"t2":
at Test.lambda$main$1(Test.java:31)
- waiting to lock <0x000000076ba1d9c0> (a java.lang.Object)
- locked <0x000000076ba1d9d0> (a java.lang.Object)
at Test$$Lambda$2/2094777811.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"t1":
at Test.lambda$main$0(Test.java:21)
- waiting to lock <0x000000076ba1d9d0> (a java.lang.Object)
- locked <0x000000076ba1d9c0> (a java.lang.Object)
at Test$$Lambda$1/1879492184.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
jconsole工具
-
jconsole工具可以实时查看一个jvm进程的内存 cpu 类加载 线程等信息。
-
使用jconsole检测内存溢出问题
-
在电脑左下角输入jconsole找到相关程序运行,然后连接到本地指定jvm进程,点击内存界面,然后就可以实时查看到该进程内存使用情况,如下可以发现内存使用不断攀升最终溢出。
-
jconsole工具来检测线程死锁问题。
-
在电脑左下角输入jconsole找到相关程序运行,然后连接到本地指定jvm进程,点击线程界面就可以对线程信息进行调试。
-
点击检测死锁就可以查看到当前程序是否发生死锁。
jvisualVM工具
-
相比于jconsole工具,jvisualVM工具除了实时查看jvm进程中内存 线程 cpu等信息外,还可以对当前内存 线程使用情况进行快照,然后进行详细分析。
-
输入jvisualvm命令 回车,然后连接指定进程。
-
在监视界面点击堆dump就可以对当前堆内存进行快照。
-
可以查看每个类的实例数和占用内存情况
-
然后可以点击查找前20最大对象,对占用内存最大的几个对象中字段进行详细分析。
-
还可以点击线程 dump 分析线程快照信息