天天看点

JDK1.8中JVM内存分析

引言

JVM内存模型分析

jvm运行时数据区模型

线程共享:堆、方法区在jdk1.8之后被转移到堆外内存,由元数据区替换掉永久代作为具体实现

线程私有:栈、本地方法栈、程序计数器

堆内存结构

以jdk1.8版本为例

堆内存分为年轻代,老年代两部分

年轻代分为Eden区、以及两个幸存区(Survivor0、Survivor1)

对象回收过程

新创建的对象会先被分配到Eden区,jvm刚启动时,Eden区对象数量较少,S0、S1两个幸存区对象几乎为空

  1. 随着时间推移,Eden区内对象数量不断增多,(Eden区空间大小可自行设置)当对象所占空间达到Eden区的容量阈值的时候,就会进行GC操作,根据可达性算法将Eden区中可达对象复制到S0区(此时S0被称作From Survivor),标记S0区对象年龄为1,并清除Eden区内所有对象,此过程称作Minor GC或Young GC
  2. 程序继续运行,Eden区再次进行GC操作,此时发现S0区已经有对象存在,将Eden区的可达对象复制到S1区(To Survivor),标记对象年龄为1,并将S0(From Survivor)区的可达对象复制到S1(To Survivor)区,标记对象年龄在原基础上加1,将S0与S1位置互换,此时S1变成 From Survivor,S0变成To Survivor,最后清空Eden区和To Survivor区,保证To Survivor始终为空
  3. 年轻代不停地进行GC操作,导致From Survivor与To Survivor之间对象反复复制,每次复制会增加已有对象的年龄,当From Survivor中对象年龄达到15的时候(对象年龄可自行设置)会被晋升到老年代,当老年代对象达到容量阈值的时候,会进行Major GC
  4. 一般情况Major GC由Minor GC触发,称作为Full GC,类似于大对象会跳过年轻代直接保存到老年代,由大对象触发的Major GC与Minor GC不存在任何关系,大对象的容量大小可自行设置

JVM调优

已被分配的内存空间未释放或者无法释放,会造成内存浪费,导致系统运行速度减慢甚至系统崩溃,称作内存泄漏

内存泄漏次数增多,会占用大量的内存空间,从而导致内存不够用,出现溢出的情况,称作内存溢出

当JVM内存受限,则需要进行JVM优化

  1. 降低GC频次:

    (1)增加老年代容量,在年轻代与老年代之间找一个平衡

    (2)降低Young GC频次来优化老年代中对象容量超限,可通过设置年轻代中对象的年龄增大(默认为15),增加S0和S1的复制次数来降低年轻代对象晋升到老年代的几率和频次

    (3)增加幸存区容量

    (4)大对象峰值的设定

  2. 缩短GC时间

    缩短老年代GC时间与降低GC频次两个做法相互排斥,想要老年代GC频次下降,就需要减小老年代空间,空间小,时间自然缩短