专栏首页墨白的Java基地JVM优化系列-------[3丶JVM的内存模型]

JVM优化系列-------[3丶JVM的内存模型]

  • 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区。

以上就是JDK1.7的内存模型介绍了,下面我们来看JDK1.8的内存模型;

  • JDK1.8的堆内存模型

由上图可以看出,JDK1.8的内存模型是由2部分组成,年轻代 + 年老代。

年轻代:Eden + 2*Survivor

年老代:OldGen

在jdk1.8中变化最大的Perm区,用Metaspace(元数据空间)进行了替换。

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

对于为什么在JDK1.8废除1.7中的永久区,官方给出了详细的解释,看下面这段话

官方原文:

地址:http://openjdk.java.net/jeps/122

1/**
2This is part of the JRockit and Hotspot convergence effort. JRockit
3customers do not need to configure the permanent generation (since JRockit
4does not have a permanent generation) and are accustomed to not
5configuring the permanent generation.
6移除永久代是为融合HotSpot JVM与 JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代。
7*/

现实使用中,由于永久代内存经常不够用或发生内存泄露,爆出异常java.lang.OutOfMemoryError: PermGen。基于此,将永久区废弃,而改用元空间,改为了使用本地内存空间。

下面我们使用jstat命令进行查看堆内存使用情况,jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。命令的格式如下:

jstat [-命令选项] [vmid/进程ID] [间隔时间/毫秒] [查询次数]

还是以tomcat为例,不熟悉今天的Linux命令的小伙伴可以查看之前的文章,里面有详细的介绍;

1== 查看tomcat的进程ID,我的是30685
2[root@localhost bin]# jps -l
330741 jdk.jcmd/sun.tools.jps.Jps
430685 org.apache.catalina.startup.Bootstrap
5== 查看class加载统计
6[root@localhost bin]# jstat -class 30685
7Loaded  Bytes  Unloaded  Bytes     Time   
8  3583  7148.2        0     0.0       4.16

来看下这些输出的数值是什么意思:

1Loaded:加载class的数量 3583
2Bytes:所占用空间大小 7148.2
3Unloaded:未加载数量 0
4Bytes:未加载占用空间 0.0
5Time:时间 4.16

所以这个命令可以很清楚的知道启动我的tomcat所加载的类有多少,占用空间大小以及耗费时间多少等等,当然,感兴趣也可以测试下别的程序,下面这个命令使我们可以查看编译的一些情况,如下:

1== 查看编译统计
2[root@localhost bin]# jstat -compiler 30685
3Compiled Failed Invalid   Time   FailedType FailedMethod
4    2495      1       0     6.95          1 java/util/Properties$LineReader readLine

说明:

1说明:
2Compiled:编译数量。 2495
3Failed:失败数量  1
4Invalid:不可用数量 0
5Time:时间 6.95 
6FailedType:失败类型 1
7FailedMethod:失败的方法 java/util/Properties$LineReader readLine

jstat命令也可以查看垃圾回收的统计,如下:

1[root@localhost bin]# jstat -gc 30685
2 S0C    S1C    S0U    S1U      EC       EU        OC        OU        MC     MU     CCSC   CCSU      YGC    YGC    FGC     FGCT     GCT   
3832.0  832.0   0.0   590.2   7168.0   1112.0   17624.0    15988.4   24960.0 23654.3 2688.0 2401.6     17    0.161   1      0.054    0.215

数值说明:

 1数值说明:
 2S0C:第一个Survivor区的大小(KB)
 3S1C:第二个Survivor区的大小(KB)
 4S0U:第一个Survivor区的使用大小(KB)
 5S1U:第二个Survivor区的使用大小(KB)
 6EC:Eden区的大小(KB)
 7EU:Eden区的使用大小(KB)
 8OC:Old区大小(KB)
 9OU:Old使用大小(KB)
10MC:方法区大小(KB)
11MU:方法区使用大小(KB)
12CCSC:压缩类空间大小(KB)
13CCSU:压缩类空间使用大小(KB)
14YGC:年轻代垃圾回收次数
15YGCT:年轻代垃圾回收消耗时间
16FGC:老年代垃圾回收次数
17FGCT:老年代垃圾回收消耗时间
18GCT:垃圾回收消耗总时间

查看垃圾回收还有另一种方式,比如可以指定打印的间隔和次数,每1秒中打印一次,共打印5次;

1[root@localhost bin]# jstat -gc 30685 1000 5
2 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC      MU     CCSC  CCSU      YGC    YGC    FGC     FGCT     GCT   
3832.0  832.0   0.0   590.2   7168.0   2524.7   17624.0    15988.4   24960.0 23654.3 2688.0 2401.6     17    0.161   1      0.054    0.215
4832.0  832.0   0.0   590.2   7168.0   2524.7   17624.0    15988.4   24960.0 23654.3 2688.0 2401.6     17    0.161   1      0.054    0.215
5832.0  832.0   0.0   590.2   7168.0   2524.7   17624.0    15988.4   24960.0 23654.3 2688.0 2401.6     17    0.161   1      0.054    0.215
6832.0  832.0   0.0   590.2   7168.0   2524.7   17624.0    15988.4   24960.0 23654.3 2688.0 2401.6     17    0.161   1      0.054    0.215
7832.0  832.0   0.0   590.2   7168.0   2524.7   17624.0    15988.4   24960.0 23654.3 2688.0 2401.6     17    0.161   1      0.054    0.215

通过jstat我们发现,依次每秒共打印了5次,上面的1000是毫秒单位;

本文分享自微信公众号 - 框架师(mohu121),作者:MoBai白

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一文精通MySQL事务规则

    引言:每个程序员学习数据库离不开MySQL,而学习MySQL就必学事务,今天我们就来一起学习一下MySQL的事务;

    框架师
  • 用Java代码实现一个在线聊天功能案例

    框架师
  • Oracle数据库相关经典面试题

    答∶ ORACLE中有两种事务 只读事务与读写事务。隔离级别 未提交读,提交读,可重复读,串行读,ORACLE支持提交读与串行读,默认隔离级别为提交读。

    框架师
  • 内存泄漏漫谈

    对于C/C++来说,内存泄漏问题一直是个很让人头痛的问题,因为对于没有GC的语言,内存泄漏的概率要比有GC的语言大得多,同时,一旦发生问题,也严重的多,而且,内...

    腾讯移动品质中心TMQ
  • 接入高防之后网站问题需要排查的有哪些?

    接入高防之后,为了保证业务最大程度的稳定,确认问题所在,墨者安全建议在切换本地的测试。本地测试步骤为:

    墨者安全筱娜
  • 机器学习算法Code Show——决策树

    上一篇文章机器学习算法复习手册——决策树在复习完基本概念之后,我给自己挖了一个坑:用python写一个决策树出来(注意,不是sklearn调包)。虽然说这个东西...

    beyondGuo
  • 死磕python(3)

    整数 在python中,python可以处理任何整数,在程序中和数学的表示上没有任何不同 浮点数 浮点数就是小数,之所以被称为浮点数的原因是因为在科学计数法中一...

    blankmiss
  • 怎样做好外贸网站推广

    外贸网站的优化和推广是网络营销中最重要的部分,有效的推广更容易促进最终成交。怎样做好外贸网站推广呢?一米软件有以下几点建议:

    用户3736847
  • velocyto-scRNAseq速率的计算

    介绍:https://www.jianshu.com/p/63071b368be5 安装:注意:velocyto 需要 python 版本>=3.6.0

    生信编程日常
  • 从零开始构建:使用CNN和TensorFlow进行人脸特征检测

    人脸检测系统在当今世界中具有巨大的用途,这个系统要求安全性,可访问性和趣味性!今天,我们将建立一个可以在脸上绘制15个关键点的模型。

    deephub

扫码关注云+社区

领取腾讯云代金券