博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JVM堆内存分配与回收策略
阅读量:2824 次
发布时间:2019-05-14

本文共 1492 字,大约阅读时间需要 4 分钟。

1、堆划分

在JDK1.7以及之前的版本中,堆内存通常被分为三块区域:新生代、老年代、永久代。

新生代又分为:Eden区、From Survivor区(S0)、To Survivor区(S1)。默认8:1:1
这里写图片描述

而在JDK1.8中情况发生了变化,把存放元数据中的永久内存从堆内存中移到了本地内存(native memory)中。

JDK1.8也提供了一个新的设置Matespace(元空间)内存大小的参数,通过这个参数可以设置Matespace内存大小,这样我们可以根据自己项目的实际情况,避免过度浪费本地内存,达到有效利用。
这里写图片描述

2、内存分配与回收策略

2.1 对象优先在Eden分配

大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够的空间进行分配时,虚拟机发起一次 Minor GC

大致过程如下:

  1. 最初一次,当Eden区满的时候,执行Minor GC,将消亡的对象清理掉,并将剩余的对象复制到一个存活区S0(此时,S1是空白的,两个Survivor总有一个是空白的),然后清空Eden区。

  2. 下次Eden区满了,再执行一次Minor GC,将消亡的对象清理掉,将存活的对象复制到S1中,然后清空Eden区。同时,将S0中消亡的对象清理掉,将其中可以晋级的对象晋级到老年代,将存活的对象也复制到S1区,然后清空S0区。

  3. 当两个存活区切换了几次(HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制)之后,仍然存活的对象将被复制到老年代。

  4. 注意:当发生Minor GC的时候,发现Survivor空间不足,部分对象无法复制到Survivor区,虚拟机通过分配担保机制将这些对象提前转移到老年代。

2.2 大对象直接进入老年代

大对象是指,需要大量连续内存空间的java对象。

最典型的的大对象有:很长的字符串以及数组。

虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配。

目的:避免在Eden区和两个Survivor区之间发生大量的内存复制(新生代采用复制算法进行GC)。

2.3 长期存活的对象将进入老年代

虚拟机给每个对象定义了一个对象年龄计数器

如果对象在Eden区出生,经过第一次Minor GC之后任然存活,并且能被Survivor区容纳,那么对象年龄设置为1。以后,对象在Survivor区中每“熬过”一次Minor GC,年龄就加1,当对象的年龄达到一定程度(默认15岁),就会晋升到老年区中。

通过参数-XX:MaxTenuringThreshold设置。

2.4 动态对象年龄判定

虚拟机并不是永远要求对象年龄达到设定值才能晋升到老年代。

如果在Survivor空间中的相同年龄(某个年龄值)所有对象大小的总和大于Survivor空间的一半,那么那些年龄大于或者等于该年龄值得对象就可以直接进入老年代。

3、空间分配担保策略

在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次Minor GC,尽管这次Minor GC是有风险的;如果小于,或者HandlePromotionFailure设置不允许冒险,那这时也要改为进行一次Full GC

你可能感兴趣的文章
Swift中strunt 和 public 的做用
查看>>
使用jmeter进行APP接口测试经验总结
查看>>
Git 代码管理常用命令
查看>>
Swift3.0 监控键盘的弹出与收回
查看>>
swift 影响Xcode编译速度的注意事项
查看>>
表的主键与外键
查看>>
win7系统重启后ip丢失问题问题的解决方法
查看>>
Win7系统用键盘替代鼠标的小技巧
查看>>
Myeclipse 10配置反编译器net.sf.jadclipse_3.3.0.jar+jad.exe
查看>>
【设计模式三之简单工厂模式】设计模式中简单工厂模式的应用----java
查看>>
关于Linux进程进程浅析(上)
查看>>
【设计模式四之工厂方法模式】java工厂方法模式
查看>>
Linux进程浅析(上)
查看>>
Linux进程浅析(中)
查看>>
exec函数和system函数
查看>>
linux下进程的信号量
查看>>
java线程浅析[初识线程]
查看>>
java线程浅析[多线程同步]
查看>>
Linux线程浅析[线程的同步和互斥之线程信号量]
查看>>
Linux进程IPC浅析[进程间通信SystemV消息队列]
查看>>