jvm的内存模型
1.JDK1.7的堆内存模型
-
Young年轻区(代)
Young区被划分为三部分,Eden区和两个大小严格相同的Survivor区,其中,Survivor区间中,某一时刻只有其中一个是被使用的,另一个用作垃圾收集时复制对象使用,在Eden区变满时,GC就会将存活的对象移动到空闲的Survivor区间中,根据jvm的策略,经历几次垃圾收集后,任然存在于Survivor的对象将被移动到Tenured区间
-
Tenured年老区
Tenured区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在Young区复制转移一定次数以后,对象就会被转移到Tenured区,一般如果系统中用了application级别的缓存,缓存中的对象往往会被转移到这一区间。
-
Perm永久区
Perm代主要保存class,method,filed这些对象,这部分空间一般不会溢出,除非一次性加载了很多类,不过在涉及到热部署的应用服务器的时候,有时候可能会遇到java.lang.OutOfMemoryError:PermGen space 的错误造成这个错误的很大原因就有可能是每次都重新部署,但是重新部署后,类的class没有被卸载掉,这就造成了大量的class对象保存在了perm中,这种情况,一般重启应用服务器就可以解决了。
-
Virtual区:
- 最大内存和初始呢村的差值,就是Virtual区
2.JDK1.8的堆内存模型
jdk1.8内存模型的年轻代(Eden+2*Survivor)和年老代(OldGen)和1.7类似,最大的变化是Perm区被Metaspace(元数据空间)进行了替换,Metaspace所占用的内存空间不是在虚拟机内部,而是在本地内存空间中,这也是与1.7永久代的最大区别之处。
3.为什么要废除1.7中的永久区
由于永久代内存经常不够用或发生内存泄露,爆出异常java.lang.OutOfMemoryError:PermGen 所以将永久区废弃,而改用元空间,改为使用了本地内存空间。
4.通过jstat命令进行查询堆内存使用情况
jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。命令格式如下:
jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]
4.1查看class加载统计
[root@iZ8vb9fnmvw0un4s5l6adsZ ~]# jps
16919 ResourceManager
19657 Bootstrap
8236 Jps
[root@iZ8vb9fnmvw0un4s5l6adsZ ~]# jstat -class 19657
Loaded Bytes Unloaded Bytes Time
3120 6131.3 13 16.6 2.06
说明:
- Loaded:加载class的数量
- Bytes:所占用空间大小
- Unloaded:未加载数量
- Bytes:未加载占用空间
- Time:时间
4.2查看编译统计
[root@iZ8vb9fnmvw0un4s5l6adsZ ~]# jstat -compiler 19657
Compiled Failed Invalid Time FailedType FailedMethod
4710 0 0 18.33 0
说明:
- Compiled:编译数量
- Failed:失败数量
- Invalid:不可用数量
- Time:时间
- FailedType:失败类型
- FailedMethod:失败的方法
4.3垃圾回收统计
[root@iZ8vb9fnmvw0un4s5l6adsZ ~]# jstat -gc 19657
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 46.2 0.0 8256.0 2019.2 20480.0 13875.6 21504.0 20684.4 2304.0 2097.3 6712 12.971 3 0.115 13.086
# 指定打印间隔和次数,每秒打印一次,供打印5次
[root@iZ8vb9fnmvw0un4s5l6adsZ ~]# jstat -gc 19657
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 46.2 0.0 8256.0 2019.2 20480.0 13875.6 21504.0 20684.4 2304.0 2097.3 6712 12.971 3 0.115 13.086
[root@iZ8vb9fnmvw0un4s5l6adsZ ~]# jstat -gc 19657 1000 5
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 46.2 0.0 8256.0 2847.5 20480.0 13875.6 21504.0 20684.4 2304.0 2097.3 6712 12.971 3 0.115 13.086
1024.0 1024.0 46.2 0.0 8256.0 2847.5 20480.0 13875.6 21504.0 20684.4 2304.0 2097.3 6712 12.971 3 0.115 13.086
1024.0 1024.0 46.2 0.0 8256.0 2847.5 20480.0 13875.6 21504.0 20684.4 2304.0 2097.3 6712 12.971 3 0.115 13.086
1024.0 1024.0 46.2 0.0 8256.0 2847.5 20480.0 13875.6 21504.0 20684.4 2304.0 2097.3 6712 12.971 3 0.115 13.086
1024.0 1024.0 46.2 0.0 8256.0 2847.5 20480.0 13875.6 21504.0 20684.4 2304.0 2097.3 6712 12.971 3 0.115 13.086
说明:
- S0C:第一个Survivor区的大小(KB)
- S1C:第二个Survivor区的大小(KB)
- S0U:第一个Survivor区的使用大小(KB)
- S1U:第二个Survivor区的使用大小(KB)
- EC:Eden区的大小
- EU:Eden区的使用大小
- OC:Old区的大小
- OU:Old区的使用大小
- MC:方法区的大小
- MU:方法区的使用大小
- CCSC:压缩类空间大小
- CCSU:压缩类空间使用大小
- YGC:年轻代垃圾回收次数
- YGCT:年轻代垃圾回收消耗的时间
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
jmap的使用以及内存溢出分析
1.查看内存使用情况
前面通过jstat可以对jvm堆的内存进行统计分析,而jmap可以获取到更加详细的内容,如:内存使用情况汇总、对内存溢出的定位于分析。
[root@iZ8vb9fnmvw0un4s5l6adsZ ~]# jps
16919 ResourceManager
19657 Bootstrap
22156 Jps
[root@iZ8vb9fnmvw0un4s5l6adsZ ~]# jmap -heap 19657
Attaching to process ID 19657, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.144-b01
using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration:# 堆内存配置信息
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 482344960 (460.0MB)
NewSize = 10485760 (10.0MB)
MaxNewSize = 160759808 (153.3125MB)
OldSize = 20971520 (20.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:#堆内存的使用情况
New Generation (Eden + 1 Survivor Space):
capacity = 9502720 (9.0625MB)
used = 8333272 (7.947227478027344MB)
free = 1169448 (1.1152725219726562MB)
87.69354458512932% used
Eden Space:
capacity = 8454144 (8.0625MB)
used = 8284672 (7.90087890625MB)
free = 169472 (0.16162109375MB)
97.9953972868217% used
From Space:
capacity = 1048576 (1.0MB)
used = 48600 (0.04634857177734375MB)
free = 999976 (0.9536514282226562MB)
4.634857177734375% used
To Space:
capacity = 1048576 (1.0MB)
used = 0 (0.0MB)
free = 1048576 (1.0MB)
0.0% used
tenured generation:
capacity = 20971520 (20.0MB)
used = 14209184 (13.550933837890625MB)
free = 6762336 (6.449066162109375MB)
67.75466918945312% used
2. 查看内存中对象数量及大小
# 查看所有对象,包括活跃以及非活跃的
jmap -histo <pid> | more
#查看活跃对象
jmap -histo:live <pid> | more
[root@iZ8vb9fnmvw0un4s5l6adsZ ~]# jmap -histo:live 19657 | more
num #instances #bytes class name
----------------------------------------------
1: 30817 3095376 [C
2: 1269 1785536 [B
3: 30529 732696 java.lang.String
4: 15723 503136 java.util.HashMap$Node
5: 4537 399256 java.lang.reflect.Method
6: 3459 391576 java.lang.Class
7: 7667 245344 java.util.concurrent.ConcurrentHashMap$Node
8: 4276 239664 [Ljava.lang.Object;
9: 910 189336 [Ljava.util.HashMap$Node;
10: 2071 159064 [I
11: 101 105840 [Ljava.util.concurrent.ConcurrentHashMap$Node;
12: 1189 104632 org.apache.catalina.webresources.CachedResource
13: 5203 83248 java.lang.Object
14: 1600 76800 java.util.HashMap
15: 1039 56416 [Ljava.lang.String;
16: 2497 53056 [Ljava.lang.Class;
17: 92 49664 [Ljava.util.WeakHashMap$Entry;
18: 1452 46464 java.util.Hashtable$Entry
19: 903 43344 org.apache.tomcat.util.modeler.AttributeInfo
20: 1082 43280 java.util.LinkedHashMap$Entry
21: 10 41120 [Ljava.nio.ByteBuffer;
22: 1232 39424 java.io.File
23: 1086 34752 java.lang.ref.WeakReference
#对象说明
B byte
C char
D double
F float
I int
J long
Z boolean
[ 数组,如[I 表示 int[]
[L+类名 其他对象
3.将内存使用情况dump到文件中
# 用法:
jmap -dump:format=b,file=dumpFileName <pid>
# 示例
[root@iZ8vb9fnmvw0un4s5l6adsZ zyh]# jps
22997 Jps
16919 ResourceManager
19657 Bootstrap
[root@iZ8vb9fnmvw0un4s5l6adsZ zyh]# jmap -dump:format=b,file=/home/zyh/dump.dat 19657
Dumping heap to /home/zyh/dump.dat ...
Heap dump file created
[root@iZ8vb9fnmvw0un4s5l6adsZ zyh]# ls
conf.d dump.dat go jvm myweb shell
4.通过jhat对dump文件进行解析
# 用法:
jhat -port <port> <file>
#示例:
[root@iZ8vb9fnmvw0un4s5l6adsZ zyh]# jhat -port 9999 /home/zyh/dump.dat
Reading from /home/zyh/dump.dat...
Dump file created Fri Dec 31 15:56:29 CST 2021
Snapshot read, resolving...
Resolving 226609 objects...
Chasing references, expect 45 dots.............................................
Eliminating duplicate references.............................................
Snapshot resolved.
Started HTTP server on port 9999
Server is ready.
# 打开浏览器访问:ip:9999