JVM内存模型

今天突然想起有道笔记有很多记录(都是18、19年)的笔记。准备从里面搬出来几个,扩充一下随笔数。O(∩_∩)O哈哈~
此文章是,自己的有道笔记,欢迎大佬斧正

jdk1.7的堆内存模型:

1.Young (新生代)
新生代 分为三部分。Eden区(new 的对象)和两个大小相同的Survivior区(某一时刻,只有一个被使用),另外一个,当Eden区满了,GC就会将存活的对象移动到空闲的Survivor区,根据JVM的策略,在经过几次垃圾收集后,依然存活在Survivor区的对象,将移动到Tenured区(老年代)

2.Tenured(老年代)
老年代 主要保存生命周期长的对象。(new 的大对象,会直接进入老年代)

3.Perm(永久代)
永久代主要保存class、method、filed对象。这部分的空间一般不会溢出,除非一次性加载很多的类,不过在涉及热部署的应用服务器的时候,有时候会遇到 java.lang.OutOfMemoryError: PermGen space的错误

jdk1.8的堆内存模型:

上图表明,jdk1.8的内存模型有2部分:年轻代+老年代
年轻代:Eden + 2*Survivor (Survivor from + Survivor to)
老年代: OldGen
在jdk1.8中变化最大是 Perm(永久区),用 Metaspace(元数据空间)进行替换
注:Metaspace所占用的内存空间不是虚拟机内部的,而是本地内存空间。

为什么要废除1.7的永久区?
1.在jdk1.8之前的HotSpot实现中,类的元数据 如 方法数据、方法信息(字节码、栈和变量的大小)、运行时常量池等被保存在永久代,32位默认永久代大小为64M,64位默认85M,可以通过参数 -XX:MaxPermSize进行设置,一旦类的元数据超过了永久代的大小,就会抛出OOM(内存过大,虚拟机死掉了)异常。
2.对永久代的调优过程非常困难,永久代的大小很难确定,其中涉及到太多因素,如类的总数,常量池大小和方法数量等,而且永久代的数据可能会随着每一次Full GC而发生移动。
3.而在jdk1.8中,类的元数据保存在本地内存中,元空间的最大可分配空间就是系统可用内存空间。
4.官网给的解释:为了融合HotSpot JVM 与 JRockit VM ,因为JRockit VM没有永久代,不需要配置永久代。

jstat 查看class加载统计:
命令:jstat -class 进程号
说明:
Loaded:加载class的数量
Bytes:所占用空间的大小
Unloaded:未加载数量
Bytes:未加载占用空间
Time:时间

jstat 查看编译统计:
命令:jstat -compiler 进程号
说明:
Compiler:编译数量
Failed:失败数量
Invalid:不可用数量
Time:时间
FailedType:失败类型
FailedMethod:失败的方法

jstat -gc <进程id>参数说明:
SOC:第一个Survivor区的大小(kb)
S1C:第二个Survivor区的大小(kb)
SOU:第一个Survivor区使用的大小(KB)
S1U:第二个Survivor区使用的大小(KB)
EC:Eden区的大小(KB)
EU:Eden区使用的大小(KB)
OC:Old区的大小(KB)
MC:方法区的大小(KB)
MU:方法区使用的大小(KB)
CCSC:压缩空间的大小(KB)
CCSU:压缩空间使用的大小(KB)
YGC:年轻代垃圾回收的次数
TGCT:年轻代垃圾回收消耗的时间
FGC:老年代垃圾回收的次数
FGCT:老年代垃圾回收消耗的时间
GCT:垃圾回收消耗总时间

posted @ 2020-08-20 11:38  cchilei  阅读(142)  评论(0编辑  收藏  举报