微信搜索superit|邀请体验:大数据, 数据管理、OLAP分析与可视化平台 | 赞助作者:赞助作者

JVM_性能调优

java aide_941 9℃

JVM_性能调优

 

https://zhuanlan.zhihu.com/p/413247306


 

OOM
Java堆溢出
java.lang.OutOfMemoryError: Java heap space
HeapByteBuffer byte[] 占用大量内存
GC overhead limit exceeded
Java栈溢出
java.lang.StackOverflowError
java.lang.OutOfMemoryError: unable to create new native thread
元空间溢出(方法区和运行时常量池)
java.lang.OutOfMemory: Metaspace
本机直接内存溢出
服务器性能分析
整机:top & uptime
CPU:vmstat & pidstat
内存:free & pidstat
硬盘:df
磁盘IO:iostat & pidstat
网络IO:ifstat
GC日志分析
案例:CPU占用过高的分析
0) 实验环境准备
1) 查找CPU占用过高的Java进程:top + jps
2) 查找该Java进程下CPU占用最高的线程:top -H -p 进程id
3) 该线程 id 十六进制的表示:printf ‘%x\n’ 线程id
4) 查看该线程堆栈情况,并进一步分析问题:jstack 进程id | grep ‘线程id的十六进制表示’ -A60
案例:内存占用过高的分析
OOM
Java OOM错误诊断方法总结

Java堆溢出
java.lang.OutOfMemoryError: Java heap space
堆无法扩展,并且无法分配对象实例时,就会抛出 java.lang.OutOfMemoryError: Java heap space 异常,即 Java 堆溢出异常

public class _2_3_HeapOOM {

static class OOMObject {
}

/**

  • VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
  • @param args
    */
    public static void main(String[] args) {
    List<OOMObject> list = new ArrayList<OOMObject>();
    while (true) {
    list.add(new OOMObject());
    }
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

/**

  • VM Options: -Xms10m -Xmx10m -XX:+PrintGCDetails
  • @param args
    */
    public static void main(String[] args) {
    String str = "atguigu";

while(true) {
str += str + new Random().nextInt(1111111111) + new Random().nextInt(2222222);
str.intern();
}
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class JavaHeapSpaceDemo {

/**

  • VM Options: -Xms10m -Xmx10m -XX:+PrintGCDetails
  • @param args
    /
    public static void main(String[] args) {
    byte[] bytes = new byte[80
    1024 * 1024];
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
HeapByteBuffer byte[] 占用大量内存
一次OOM故障分析记录:HeapByteBuffer byte[] 占用了大量内存
记一次OOM问题排查过程
JVM 参数配置

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp/bsd-shoes-message.hprof
1
2
server:
servlet:
context-path: /test
port: 8004
max-http-header-size: 64KB
1
2
3
4
5
GC overhead limit exceeded
OutOfMemoryError系列(2): GC overhead limit exceeded
OutOfMemoryError系列(2): GC overhead limit exceeded
GC overhead limit exceeded原因分析及解决方案

public class GCOverHeadLimitExceeded {

/**

  • GC overhead limit exceeded
  • VM: -ea -Xmx12m -XX:+UseParallelGC
  • @param args
  • @throws Exception
    */
    public static void main(String args[]) throws Exception {
    Map map = System.getProperties();
    Random r = new Random();
    while (true) {
    map.put(r.nextInt(), "value");
    System.out.println("program is running …");
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Java栈溢出
    java.lang.StackOverflowError
    线程请求的栈深度大于虚拟机栈所允许的最大深度时,将抛出 StackOverflowError 异常

public class _2_4_JavaVMStackSOF {

private int stackLength = 1;

public void stackLeak() {
stackLength++;
stackLeak();
}

public static void main(String[] args) throws Throwable {
_2_4_JavaVMStackSOF oom = new _2_4_JavaVMStackSOF();
try {
oom.stackLeak();
} catch (Throwable e) {
System.out.println("stack length:" + oom.stackLength);
throw e;
}
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class _2_5_JavaVMStackSOF {

private static int stackLength = 0;

public static void test() {
long unused1, unused2, unused3, unused4, unused5,
unused6, unused7, unused8, unused9, unused10,
unused11, unused12, unused13, unused14, unused15,
unused16, unused17, unused18, unused19, unused20,
unused21, unused22, unused23, unused24, unused25,
unused26, unused27, unused28, unused29, unused30,
unused31, unused32, unused33, unused34, unused35,
unused36, unused37, unused38, unused39, unused40,
unused41, unused42, unused43, unused44, unused45,
unused46, unused47, unused48, unused49, unused50,
unused51, unused52, unused53, unused54, unused55,
unused56, unused57, unused58, unused59, unused60,
unused61, unused62, unused63, unused64, unused65,
unused66, unused67, unused68, unused69, unused70,
unused71, unused72, unused73, unused74, unused75,
unused76, unused77, unused78, unused79, unused80,
unused81, unused82, unused83, unused84, unused85,
unused86, unused87, unused88, unused89, unused90,
unused91, unused92, unused93, unused94, unused95,
unused96, unused97, unused98, unused99, unused100;
stackLength++;
test();
unused1 = unused2 = unused3 = unused4 = unused5 =
unused6 = unused7 = unused8 = unused9 = unused10 =
unused11 = unused12 = unused13 = unused14 = unused15 =
unused16 = unused17 = unused18 = unused19 = unused20 =
unused21 = unused22 = unused23 = unused24 = unused25 =
unused26 = unused27 = unused28 = unused29 = unused30 =
unused31 = unused32 = unused33 = unused34 = unused35 =
unused36 = unused37 = unused38 = unused39 = unused40 =
unused41 = unused42 = unused43 = unused44 = unused45 =
unused46 = unused47 = unused48 = unused49 = unused50 =
unused51 = unused52 = unused53 = unused54 = unused55 =
unused56 = unused57 = unused58 = unused59 = unused60 =
unused61 = unused62 = unused63 = unused64 = unused65 =
unused66 = unused67 = unused68 = unused69 = unused70 =
unused71 = unused72 = unused73 = unused74 = unused75 =
unused76 = unused77 = unused78 = unused79 = unused80 =
unused81 = unused82 = unused83 = unused84 = unused85 =
unused86 = unused87 = unused88 = unused89 = unused90 =
unused91 = unused92 = unused93 = unused94 = unused95 =
unused96 = unused97 = unused98 = unused99 = unused100 = 0;
}

public static void main(String[] args) {
try {
test();
} catch (Error e) {
System.out.println("stack length:" + stackLength);
throw e;
}
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class StackOverflowErrorDemo {

public static void main(String[] args) {
stackOverflowError();
}

private static void stackOverflowError() {
stackOverflowError();
}

}
1
2
3
4
5
6
7
8
9
10
11
java.lang.OutOfMemoryError: unable to create new native thread
线程栈无法为线程的创建分配足够的内存时,抛出java.lang.OutOfMemoryError: unable to create new native thread异常

public class UnableCreateNewThreadDemo {

public static void main(String[] args) {
for (int i = 1; ; i++) {
System.out.println("*****i = " + i);
new Thread(() -> {
try { Thread.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { e.printStackTrace(); }
}, "" + i).start();
}
}

}
1
2
3
4
5
6
7
8
9
10
11
12
元空间溢出(方法区和运行时常量池)
java.lang.OutOfMemory: Metaspace
本机直接内存溢出
服务器性能分析
整机:top & uptime
CPU:vmstat & pidstat
pidstat -u -p 9 1 # 每 1s 采样一次 进程id=9 的CPU信息并打印
1
内存:free & pidstat

pidstat -r -p 1774 2 # 每 2s 采样一次 进程id=1774 的内存信息并打印
1
硬盘:df
磁盘IO:iostat & pidstat
pidstat -d -p 1775 2 # 每 2s 采样一次 进程id=1775 的磁盘IO信息并打印
1
网络IO:ifstat
GC日志分析
java8 GC日志分析
JVM GC 日志详解
GC之详解CMS收集过程和日志分析
JVM垃圾回收机制入门
JDK1.8 GC日志查看(参考深入理解JAVA虚拟机)
第22课:通过案例瞬间理解JVM中PSYoungGen、ParOldGen、MetaSpace
GC日志分析

public class _2_3_HeapOOM {

static class OOMObject {
}

/**

  • VM Args: -Xms20m -Xmx20m -XX:+PrintGCDetails
  • @param args
    */
    public static void main(String[] args) {
    List<OOMObject> list = new ArrayList<>();
    while (true) {
    list.add(new OOMObject());
    }
    }

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
案例:CPU占用过高的分析
记录一次生产CPU使用率100%问题排查
记录一次生产CPU使用率100%问题排查
线上java程序CPU占用过高问题排查
记一次java程序CPU占用过高问题排查

0) 实验环境准备
编写如下代码并运行,模拟一个正在运行的 java 应用

package com.java.atguigu.interview_2._105;

import java.util.Random;

public class JavaDemo02 {

public static void main(String[] args) {
while (true) {
System.out.println(new Random().nextInt(77778888));
}
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
1) 查找CPU占用过高的Java进程:top + jps
2) 查找该Java进程下CPU占用最高的线程:top -H -p 进程id
top -H -p 进程id # 查看进程下的线程

top -H -p 15548 # 查看进程 15548 下的线程
1
2
3

3) 该线程 id 十六进制的表示:printf ‘%x\n’ 线程id
printf ‘%x\n’ 线程id # 线程 id 的十六进制表示

printf ‘%x\n’ 15740 # 线程 15740 的十六进制表示
1
2
3

4) 查看该线程堆栈情况,并进一步分析问题:jstack 进程id | grep ‘线程id的十六进制表示’ -A60
jstack 进程id | grep ‘线程id的十六进制表示’ -A60

jstack 15548 | grep ‘0x3d7c’ -C50 # 查看进程 15548 下的线程 0x3d7c 的堆栈情况,显示前 50 行
jstack 15548 | grep ‘0x3d7c’ -A60 # 查看进程 15548 下的线程 0x3d7c 的堆栈情况,显示前 60 行
1
2
3
4

案例:内存占用过高的分析
查找进程id: 【top -d 2 -c】
查看JVM堆内存分配情况:jmap -heap pid
查看占用内存比较多的对象 jmap -histo pid | head -n 100
查看占用内存比较多的存活对象 jmap -histo:live pid | head -n 100
————————————————
版权声明:本文为CSDN博主「4change」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/CSDN_FlyYoung/article/details/123206912

转载请注明:SuperIT » JVM_性能调优

喜欢 (0)or分享 (0)