为什么80%的码农都做不了架构师?>>>
常见原因
- 内存分配过小,与实际业务需要空间不符。
- 对象频繁被创建,却没有被释放,导致内存泄漏。
- 有限系统资源(线程、网络连接)被不断的申请,导致系统资源被耗尽。
问题排查
查看内存分配空间
获取java进程:
[root@hostname ~]# ps x | grep java | grep -v grep
2248 ? Sl 0:37 /usr/local/java/jdk1.7.0_55/bin/java -Xms64M -Xmx1G -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=/usr/local/apache-activemq-5.13.0//conf/login.config -Dcom.sun.management.jmxremote -Djava.awt.headless=true -Djava.io.tmpdir=/usr/local/apache-activemq-5.13.0//tmp -Dactivemq.classpath=/usr/local/apache-activemq-5.13.0//conf:/usr/local/apache-activemq-5.13.0//../lib/ -Dactivemq.home=/usr/local/apache-activemq-5.13.0/ -Dactivemq.base=/usr/local/apache-activemq-5.13.0/ -Dactivemq.conf=/usr/local/apache-activemq-5.13.0//conf -Dactivemq.data=/usr/local/apache-activemq-5.13.0//data -jar /usr/local/apache-activemq-5.13.0//bin/activemq.jar start
2615 ? Sl 0:21 /usr/local/java/jdk1.7.0_55/bin/java -Djava.util.logging.config.file=/usr/local/src/apache-tomcat-7.0.47/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/src/apache-tomcat-7.0.47/endorsed -classpath /usr/local/src/apache-tomcat-7.0.47/bin/bootstrap.jar:/usr/local/src/apache-tomcat-7.0.47/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/src/apache-tomcat-7.0.47 -Dcatalina.home=/usr/local/src/apache-tomcat-7.0.47 -Djava.io.tmpdir=/usr/local/src/apache-tomcat-7.0.47/temp org.apache.catalina.startup.Bootstrap start
以2248为例,获取java堆内存信息:
[root@hostname ~]# jmap -heap 2248
Attaching to process ID 2248, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 24.55-b03
using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB)
NewSize = 1048576 (1.0MB)
MaxNewSize = 4294901760 (4095.9375MB)
OldSize = 4194304 (4.0MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 12582912 (12.0MB)
MaxPermSize = 67108864 (64.0MB)
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 20250624 (19.3125MB)
used = 11778664 (11.233009338378906MB)
free = 8471960 (8.079490661621094MB)
58.16444964856392% used
Eden Space:
capacity = 18022400 (17.1875MB)
used = 10298688 (9.82159423828125MB)
free = 7723712 (7.36590576171875MB)
57.14382102272727% used
From Space:
capacity = 2228224 (2.125MB)
used = 1479976 (1.4114151000976562MB)
free = 748248 (0.7135848999023438MB)
66.41953412224265% used
To Space:
capacity = 2228224 (2.125MB)
used = 0 (0.0MB)
free = 2228224 (2.125MB)
0.0% used
tenured generation:
capacity = 44761088 (42.6875MB)
used = 21501792 (20.505706787109375MB)
free = 23259296 (22.181793212890625MB)
48.03679481606881% used
Perm Generation:
capacity = 18874368 (18.0MB)
used = 18696632 (17.83049774169922MB)
free = 177736 (0.16950225830078125MB)
99.05832078721788% used
12663 interned Strings occupying 1650096 bytes.
对堆内存的使用情况进行分析,可以作为内存是否分配过小的依据。
寻找最耗内存的对象
查看方法(线上环境一定要慎用,该命令会导致jvm进行一次full GC):
[root@hostname ~]# jmap -histo:live 2248 | less
结果样例:
num #instances #bytes class name
----------------------------------------------
1: 53225 6549440
2: 14540 5446408 [B
3: 25896 4873976 [C
4: 53225 3837240
5: 4762 2886816
6: 1869 2196520 [I
7: 4762 1913208
8: 3914 1526064
9: 5156 617792 java.lang.Class
10: 24970 599280 java.lang.String
11: 6981 381064 [S
12: 7812 371952 [[I
13: 3247 259760 java.lang.reflect.Method
14: 10474 251376 java.util.concurrent.ConcurrentHashMap$HashEntry
15: 4157 198456 [Ljava.lang.Object;
16: 1135 170712 [Ljava.util.HashMap$Entry;
17: 3656 116992 java.lang.ref.SoftReference
18: 377 114608
19: 3360 107520 java.util.LinkedHashMap$Entry
20: 702 101784 [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;
21: 3935 94440 java.lang.ref.WeakReference
22: 2374 93168 [Ljava.lang.String;
23: 10622 84976 java.lang.Object
24: 3308 79392 java.util.HashMap$Entry
25: 3195 76680 java.util.ArrayList
26: 1378 66144 java.beans.MethodDescriptor
27: 1181 66136 java.util.LinkedHashMap
28: 677 64992 org.springframework.beans.GenericTypeAwarePropertyDescriptor
29: 701 44864 java.lang.reflect.Constructor
30: 696 44544 java.beans.PropertyDescriptor
31: 862 41376 java.util.HashMap
32: 1616 38784 java.util.concurrent.locks.ReentrantLock$NonfairSync
33: 2140 35624 [Ljava.lang.Class;
34: 336 34944 java.net.SocksSocketImpl
...省略
定位问题时,主要关注点在instance较多,且内存占用较大的实例或者类,有针对性的进行排查分析。
确认资源是否耗尽
查看线程数:
[root@hostname ~]# pstree -p 2248
java(2248)─┬─{java}(2279)
├─{java}(2285)
├─{java}(2286)
├─{java}(2287)
├─{java}(2290)
├─{java}(2291)
├─{java}(2292)
...为节约篇幅省略
统计线程数:
[root@hostname ~]# pstree -p 2248 | wc -l
42
查看网络连接:
[root@hostname ~]# netstat -naput | grep 2248
tcp 0 0 :::5672 :::* LISTEN 2248/java
tcp 0 0 :::50284 :::* LISTEN 2248/java
tcp 0 0 :::61613 :::* LISTEN 2248/java
tcp 0 0 :::61614 :::* LISTEN 2248/java
tcp 0 0 :::61616 :::* LISTEN 2248/java
tcp 0 0 :::1883 :::* LISTEN 2248/java
tcp 0 0 :::8161 :::* LISTEN 2248/java
udp 0 0 :::24884 :::*