当前位置 > it书童 > java > 正文

jvm 内存模型

java it书童 2020-12-24 20:03:32 0赞 0踩 435阅读 0评论

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中,这种情况下,一般重新启动应用服务器可以解决问题

jdk1.8 的堆内存模型

在jdk1.8中变化最大的Perm区,用Metaspace(元数据空间)进行了替换。所以堆内存模型只由2部分组成

  • 年轻代:Eden + 2*Survivor

  • 年老代:OldGen

需要特别说明的是:Metaspace所占用的内存空间不是在虚拟机内部,而是在本地内存空间中,这也是与1.7的永久代最大的区别所在。

移除永久代是为融合HotSpot JVM与 JRockit VM而做出的努力,因为JRockit没有永久代, 不需要配置永久代。而且现实使用中,永久代内存经常不够用或发生内存泄露。基于此,将永久区废弃,而改用元空间,改为了使用本地内存空间

jstat查看堆内存使用情况

查看 class 加载统计

$ jps -l
4628 org.apache.catalina.startup.Bootstrap
4887 sun.tools.jps.Jps
$ jstat -class 4628
Loaded  Bytes  Unloaded  Bytes     Time
  3257  6506.8        0     0.0       2.20

说明:

Loaded: 加载class的数量

Bytes: 所占用空间大小

Unloaded: 未加载数量

Bytes: 未加载占用空间

Time: 时间

查看编译统计

$ jstat -compiler 4628
Compiled Failed Invalid   Time   FailedType FailedMethod
    2402      1       0     4.63          1 java/net/URL getURLStreamHandler

说明:

Compiled: 编译数量

Failed: 失败数量

Invalid: 不可用数量

Time: 时间

FailedType: 失败类型

FailedMethod: 失败的方法

垃圾回收统计

$ jstat -gc 4628
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
5120.0 5120.0 5104.0  0.0   66560.0  62374.0   87552.0     7288.8   17664.0 17206.0 2048.0 1888.2      2    0.034   0      0.000    0.034

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:垃圾回收消耗总时间

jmap的使用以及内存溢出分析

通过jstat可以对jvm堆的内存进行统计分析,而jmap可以获取到更加详细的内容,如:内存使用情况的汇总、对内存溢出的定位与分析

使用 jmap 命令也能看到使用情况,但不太直观,最好生成一个文件,再用专业的工具生成使用报表

$ jmap -dump:format=b,file=/tmp/dump.dat 4628

$ jhat -port 9999 /tmp/dump.dat

访问 http://127.0.0.1:9999/

自带的 jhat 工具过于简陋,mat 更加专业

mat 官网下载

MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速、功能丰富的JAVA heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。使用内存分析工具从众多的对象中进行分析,快速的计算出在内存中对象的占用大小,看看是谁阻止了垃圾收集器的回收工作,并可以通过报表直观的查看到可能造成这种结果的对象

导入文件

生成报表

关于我
一个文科出身的程序员,追求做个有趣的人,传播有价值的知识,微信公众号主要分享读书思考心得,不会有代码类文章,非程序员的同学请放心订阅
转载须注明出处:https://www.itshutong.com/articles/986