参考链接:www.cnblogs.com/Dhouse/p/78…
java启动项:
Xms 是指设定程序启动时占用内存大小
Xmx 是指设定程序运行期间最大可占用的内存大小(如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常。)
Xmn 是指年轻代大小
Xss 是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程大约需要占用多少内存,可能会有多少线程同时运行等。
# 启动项增加GC配置:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log
1、高CPU占用
ps -mp pid -o THREAD,tid,time
printf "%x\n" tid
# 最后打印线程的堆栈信息:
# jstack:Java提供的命令。可以查看某个进程的当前线程栈运行情况。
# 根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等等。
jstack pid |grep tid -A 30
2、高内存占用
一般情况:
1、java.lang.OutOfMemoryError: PermGen space
2、java.lang.OutOfMemoryError: Java heap space #java1.8后已经讲永久代去除,只有元空间了,因此不会出现这个问题
在Java虚拟机中,内存分为三个代:新生代(New)、老生代(Old)、永久代(Perm)
(1)新生代New:新建的对象都存放这里
(2)老生代Old:存放从新生代New中迁移过来的生命周期较久的对象。新生代New和老生代Old共同组成了堆内存。
(3)永久代Perm:是非堆内存的组成部分。主要存放加载的Class类级对象如class本身,method,field等等。
一、java.lang.OutOfMemoryError: Java heap spac #说明Java虚拟机的堆内存不够,Java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整。
二、java.lang.OutOfMemoryError: PermGen space #说明是Java虚拟机对永久代Perm内存设置不够。一般出现这种情况,都是程序启动需要加载大量的第三方jar包。
# 内存占用高的实例:
ps -mp pid -o THREAD,tid,time,rss,size,%mem
#jmap查看内存情况,什么class有多少
#可以查看当前Java进程创建的活跃对象数目和占用内存大小
jmap -histo:live pid
# YGC就是年轻代GC, FGC就是FullGC, T就是时间
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 1.12 1.15 98.13 96.38 9 0.049 2 0.056 0.105
0.00 0.00 1.12 1.15 98.13 96.38 9 0.049 2 0.056 0.105
0.00 0.00 1.12 1.15 98.13 96.38 9 0.049 2 0.056 0.105
0.00 0.00 1.12 1.15 98.13 96.38 9 0.049 2 0.056 0.105
0.00 0.00 1.12 1.15 98.13 96.38 9 0.049 2 0.056 0.105
#则可以将当前Java进程的内存占用情况导出来,方便用专门的内存分析工具(例如:MAT)来分析。
jmap -dump:live,format=b,file=jamp.log pid #会导致full gc, 因此执行该命令需谨慎
#jstat动态查看年轻代,老年代的gc情况
jstat -gcutil 17604 #会导致full gc, 因此执行该命令需谨慎
#下面就是类的名,有多少实例,占用了多少内存
num #instances #bytes class name
----------------------------------------------
1: 10545 805704 [C
2: 567 353336 [J
3: 2393 271800 java.lang.Class
4: 470 254944 [B
5: 10506 252144 java.lang.String
6: 2521 128512 [I
7: 1855 99608 [Ljava.lang.Object;
8: 2707 86624 java.util.concurrent.ConcurrentHashMap$Node
9: 1989 63648 java.util.HashMap$Node
10: 613 53944 java.lang.reflect.Method
11: 751 42056 sun.util.calendar.ZoneInfo
12: 355 36248 [Ljava.util.HashMap$Node;
13: 1777 28432 java.lang.Object
14: 666 26640 java.util.LinkedHashMap$Entry
15: 51 26296 [Ljava.util.concurrent.ConcurrentHashMap$Node;
16: 423 16920 java.lang.ref.SoftReference
17: 483 16512 [Ljava.lang.String;
JVM内存如何进行和常用分析命令汇总:
(1)如何分配内存
# 根据gc的情况,看年轻代和老年代的内存设置
1、直接使用默认的启动,然后查看gc情况
2、根据开发本地电脑的配置来设置
3、后期根据gc情况调整具体的大小
(2)常用分析命令
[root@stage-lab-api ~]# jstat -gcutil 17604 1000
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 1.12 1.15 98.13 96.38 9 0.049 2 0.056 0.105
0.00 0.00 1.12 1.15 98.13 96.38 9 0.049 2 0.056 0.105
0.00 0.00 1.12 1.15 98.13 96.38 9 0.049 2 0.056 0.105
0.00 0.00 1.12 1.15 98.13 96.38 9 0.049 2 0.056 0.105
0.00 0.00 1.12 1.15 98.13 96.38 9 0.049 2 0.056 0.105
[root@stage-lab-api ~]# jmap -histo:live 17604 | head -n 20 #(这个命令会导致gc)
num #instances #bytes class name
----------------------------------------------
1: 10545 805704 [C
2: 567 353336 [J
3: 2393 271800 java.lang.Class
4: 470 254944 [B
5: 10506 252144 java.lang.String
6: 2521 128512 [I
7: 1855 99608 [Ljava.lang.Object;
8: 2707 86624 java.util.concurrent.ConcurrentHashMap$Node
9: 1989 63648 java.util.HashMap$Node
10: 613 53944 java.lang.reflect.Method
11: 751 42056 sun.util.calendar.ZoneInfo
12: 355 36248 [Ljava.util.HashMap$Node;
13: 1777 28432 java.lang.Object
14: 666 26640 java.util.LinkedHashMap$Entry
15: 51 26296 [Ljava.util.concurrent.ConcurrentHashMap$Node;
16: 423 16920 java.lang.ref.SoftReference
17: 483 16512 [Ljava.lang.String;
[root@pd-disp-gateway ~]# jmap -heap 10513
Attaching to process ID 10513, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.192-b12
using thread-local object allocation.
Parallel GC with 4 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 2147483648 (2048.0MB)
NewSize = 268435456 (256.0MB)
MaxNewSize = 268435456 (256.0MB)
OldSize = 1879048192 (1792.0MB)
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 = 263192576 (251.0MB)
used = 9582776 (9.138847351074219MB)
free = 253609800 (241.86115264892578MB)
3.640975040268613% used
From Space:
capacity = 2621440 (2.5MB)
used = 0 (0.0MB)
free = 2621440 (2.5MB)
0.0% used
To Space:
capacity = 2621440 (2.5MB)
used = 0 (0.0MB)
free = 2621440 (2.5MB)
0.0% used
PS Old Generation
capacity = 1879048192 (1792.0MB)
used = 27599024 (26.320480346679688MB)
free = 1851449168 (1765.6795196533203MB)
1.4687768050602503% used
22532 interned Strings occupying 2936192 bytes.
(3)OOM分析
最常见的OOM情况有以下三种:
java.lang.OutOfMemoryError: Java heap space ------>
java堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改。
# java8中,永久代被换成了元空间,不会再出现以下情况,当然也可以再java8中限制。
java.lang.OutOfMemoryError: PermGen space ------>
java永久代溢出,即方法区溢出了,一般出现于大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。
java.lang.StackOverflowError ------>
不会抛OOM error,但也是比较常见的Java内存溢出。JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。
(4)GC OOM发生条件:
对象一般在新生代的Eden区分配空间,大对象(超过阈值)和(大)数组会直接在老年代分配;
JVM默认老年代和年轻代空间比例3:1,新生代默认Eden和survivor区比例8:1(两个survivor,所以是8:1:1);
如果新生代空间不够(触发阈值),会触发minor GC,回收年轻代的垃圾,使用复制算法,超过阈值年龄的存活对象会进入老年代;
如果分配空间时老年代空间不够(达到阈值),会触发major GC(就是FUll GC),算法根据垃圾收集器的不同而有所差别,Full GC 之后还是不够,就会抛出OOM错误。
Java 8没有永久代,MetaSpace是堆外内存
元空间与永久代最大的区别在于,元空间不在虚拟机中,使用本地内存。通过配置如下参数可以更改元空间的大小。
-XX:MetaspaceSize:初始空间的大小。达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
-XX:MaxMetaspaceSize,最大空间,默认是没有限制的。
永久代的回收会随着full gc进行移动,消耗性能。每种类型的垃圾回收都需要特殊处理元数据。将元数据剥离出来,简化了垃圾收集,提高了效率。