JVM内存模型
Java内存模型(Java Memory Model ,JMM)就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。 根据java虚拟机的规范,我们可以将JVM的内存分为五大块
This is part of the JRockit and Hotspot convergence effort. JRockit
customers do not need to configure the permanent generation (since JRockit
does not have a permanent generation) and are accustomed to not
configuring the permanent generation.
移除永久代是为融合HotSpot JVM与 JRockit VM而做出的努力,因为JRockit没有永久代,
不需要配置永久代
现实使用中,由于永久代内存经常不够用或发生内存泄露,爆出异常
java.lang.OutOfMemoryError: PermGen。
基于此,将永久区废弃,而改用元空间,改为了使用本地内存空间。
jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。命令的格式如下: jstat [-命令选项] [端口号] [间隔时间/毫秒] [查询次数] 常用的有三个命令选项
解释: Loaded:加载class的数量 Bytes:所占用空间大小 Unloaded:未加载数量 Bytes:未加载占用空间 Time:时间
[root@hadoop101 ~]# jstat -compiler 3846
Compiled Failed Invalid Time FailedType FailedMethod
2174 0 0 6.38 0
解释: Compiled:编译数量。 Failed:失败数量 Invalid:不可用数量 Time:时间 FailedType:失败类型 FailedMethod:失败的方法
[root@hadoop101 ~]# jstat -gc 3846
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1536.0 1536.0 0.0 32.6 12352.0 3144.9 30820.0 20681.0 25344.0 24556.2 2816.0 2588.3 15 0.417 1 0.075 0.493
# 间隔1秒 收集五次
[root@hadoop101 ~]# jstat -gc 3846 1000 5
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1536.0 1536.0 0.0 32.6 12352.0 3144.9 30820.0 20681.0 25344.0 24556.2 2816.0 2588.3 15 0.417 1 0.075 0.493
1536.0 1536.0 0.0 32.6 12352.0 3144.9 30820.0 20681.0 25344.0 24556.2 2816.0 2588.3 15 0.417 1 0.075 0.493
1536.0 1536.0 0.0 32.6 12352.0 3144.9 30820.0 20681.0 25344.0 24556.2 2816.0 2588.3 15 0.417 1 0.075 0.493
1536.0 1536.0 0.0 32.6 12352.0 3144.9 30820.0 20681.0 25344.0 24556.2 2816.0 2588.3 15 0.417 1 0.075 0.493
1536.0 1536.0 0.0 32.6 12352.0 3144.9 30820.0 20681.0 25344.0 24556.2 2816.0 2588.3 15 0.417 1 0.075 0.493
解释:(你会发现总有一个survivor是空的,这也印证了我上面说到的年轻代的存储方式) S0C:第一个Survivor区的大小(KB) S1C:第二个Survivor区的大小(KB) S0U:第一个Survivor区的使用大小(KB) S1U:第二个Survivor区的使用大小(KB) EC:Eden区的大小(KB) EU:Eden区的使用大小(KB) OC:Old区大小(KB) OU:Old使用大小(KB) MC:方法区大小(KB) MU:方法区使用大小(KB) CCSC:压缩类空间大小(KB) CCSU:压缩类空间使用大小(KB) YGC:年轻代垃圾回收次数 YGCT:年轻代垃圾回收消耗时间 FGC:老年代垃圾回收次数 FGCT:老年代垃圾回收消耗时间 GCT:垃圾回收消耗总时间
前面通过jstat可以对jvm堆的内存进行统计分析,而jmap可以获取到更加详细的内容, 如:内存使用情况的汇总、对内存溢出的定位与分析。
指令格式:jmap -heap 端口号
[root@hadoop101 ~]# jmap -heap 3846
Attaching to process ID 3846, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.111-b14
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 = 14221312 (13.5625MB)
used = 4445184 (4.2392578125MB)
free = 9776128 (9.3232421875MB)
31.257200460829495% used
Eden Space: # Eden 使用情况
capacity = 12648448 (12.0625MB)
used = 4411808 (4.207427978515625MB)
free = 8236640 (7.855072021484375MB)
34.880231946243526% used
From Space: # From Surivior 使用情况
capacity = 1572864 (1.5MB)
used = 33376 (0.031829833984375MB)
free = 1539488 (1.468170166015625MB)
2.1219889322916665% used
To Space: # To Survivor 使用情况
capacity = 1572864 (1.5MB)
used = 0 (0.0MB)
free = 1572864 (1.5MB)
0.0% used
tenured generation: # 老年代
capacity = 31559680 (30.09765625MB)
used = 21177312 (20.196258544921875MB)
free = 10382368 (9.901397705078125MB)
67.10242942894224% used
13885 interned Strings occupying 1883624 bytes.
查看所有对象,包括活跃以及非活跃的 jmap ‐histo 端口号 | more 查看活跃对象 jmap ‐histo:live 端口号 | more
[root@hadoop101 ~]# jmap -histo:live 3846 | more
num #instances #bytes class name
----------------------------------------------
1: 36197 6581296 [C
2: 3052 1689256 [I
3: 985 1004736 [B
4: 34556 829344 java.lang.String
5: 15257 488224 java.util.HashMap$Node
6: 4042 466008 java.lang.Class
7: 4453 391864 java.lang.reflect.Method
8: 4214 265160 [Ljava.lang.Object;
9: 6799 217568 java.util.concurrent.ConcurrentHashMap$Node
10: 977 175600 [Ljava.util.HashMap$Node;
11: 89 104880 [Ljava.util.concurrent.ConcurrentHashMap$Node;
12: 5975 95600 java.lang.Object
13: 1177 84016 [Ljava.lang.String;
14: 1615 77520 java.util.HashMap
15: 2602 54072 [Ljava.lang.Class;
16: 89 49424 [Ljava.util.WeakHashMap$Entry;
17: 608 48640 java.lang.reflect.Constructor
18: 1430 45760 java.util.Hashtable$Entry
19: 1096 43840 java.lang.ref.SoftReference
20: 1047 41880 java.util.LinkedHashMap$Entry
21: 1027 41080 java.util.TreeMap$Entry
22: 837 40176 org.apache.tomcat.util.modeler.AttributeInfo
23: 9 37008 [Ljava.nio.ByteBuffer;
24: 52 35264 [S
25: 125 34416 [[C
26: 974 31168 java.lang.ref.WeakReference
27: 1180 28320 java.util.ArrayList
解释: B byte C char D double F float I int J long Z boolean [ 数组,如[I表示int[] [L+类名 其他对象
有些时候我们需要将jvm当前内存中的情况dump到文件中,然后对它进行分析,jmap也 是支持dump到文件中的 语法:jmap ‐dump:format=b,file=目标文件全路径 端口号
[root@hadoop101 ~]# jmap -dump:format=b,file=dump.dat 3846
Dumping heap to /root/dump.dat ...
Heap dump file created
[root@hadoop101 ~]# ll
total 37788
-rw-------. 1 root root 5418 Apr 6 2017 anaconda-ks.cfg
-rw-------. 1 root root 29300407 Aug 14 14:16 dump.dat
drwxr-xr-x. 2 root root 6 Aug 14 08:54 jvm
-rw-r--r--. 1 root root 571 Aug 14 10:32 JvmTest.class
-rw-r--r--. 1 root root 250 Aug 14 08:56 JvmTest.java
-rw-r--r--. 1 root root 9366128 Apr 4 2017 node-v6.10.2-linux-x64.tar.xz
-rw-------. 1 root root 5098 Apr 6 2017 original-ks.cfg
[root@hadoop101 ~]#
我们将jvm的内存dump到文件中,这个文件是一个二进制的文件,不方便查看,这时我们可以借助于jhat工具进行查看。 语法: jhat ‐port 浏览器访问端口号 文件
[root@hadoop101 ~]# jhat -port 8081 dump.dat
Reading from dump.dat...
Dump file created Wed Aug 14 14:16:57 UTC 2019
Snapshot read, resolving...
Resolving 271656 objects...
Chasing references, expect 54 dots......................................................
Eliminating duplicate references......................................................
Snapshot resolved.
Started HTTP server on port 8081
Server is ready.
我们可以通过服务器ip:8081查看 在最后还有一个OQL的查询功能,语法类似SQL,可以快速查询到想要看的数据