JVM学习——3.3 垃圾清理-内存分配

JVM内存管理

通常我们说JVM说的自动内存管理主要包含:自动化解决给对象分配内存以及自动化的回收分配给对象的内存。之前学习过垃圾回收算法以及运行原理,现在来学习对象内存分配。

对象的内存分配,主要介绍的是在堆上进行内存分配。

  1. 对象的最开始主要分配在新生代的Eden区上。
  2. 如果启动本地线程分配缓冲,线程优先分配在TLAB上。
  3. 少数直接分配在老年代中

对象优先在Eden分配

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

大对象直接进入老年代

所谓的大对象,就是需要大量连续内存的JAVA对象

一般说大对象,比较典型的就是很长字符串以及数组。频繁的出现大对象可能导致内存空间还存在不少空间的时候进提前触发垃圾收集,以保证系统有足够连续的空间来保存这些对象。

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

分代收集的思想是收集器根据历史经验对对象收集进行优化。

假如要进行分代收集,很重要一个条件就是需要确定哪些对象属于新生代哪些对象属于老年代。为了区分这些对象。JVM引入了一个对象的定义:年龄计数器。

如果对象在Eden出生并经过一次GC,那么当Survivor存在空间的时候会被转移至Survivor,并设置其年龄。对象在Survivor中每熬过一次GC,年龄就加一,当期年龄达到一个限值后会被提升至老年代。

动态对象年龄判定

当你设置了年龄限值(-XX:MaxTenuringThreshold),但JVM并非一定要年龄叨叨这个限值才能提升至老年代。为了适应不同情况的内存场景,如果在Survivor中相同年龄所有对象大小大于Survivor空间的一半,年龄大于或等于该年龄的对象就有可以直接进入老年代。

空间分配担保

在Minor GC(新生代GC)之前,JVM会检查老年代最大可用的连续空间是否大于新生代所有对象总空间。

  • 如果老年代最大可用空间大于新生代对象总空间,则GC可以确保是安全的。
  • 如果不成立则虚拟机则查看是否设置了允许担保失败,如果允许则检查老年代最大可用的连续空间是否大于历次提升到老年代对象的大小。
    • 如果大于,则尝试进行GC,尽管是存在风险的。
    • 如果小于或者设置了不允许担保失败则进行一次full GC (老年代GC)

Minor GC的风险

上面说到的风险,主要来自于,新生代使用了复制收集算法,但是只使用了启动一个Survivor空间作为轮换内存。因此当大量对象在Minor GC后依然存在的时候,就需要老年代进行分配担保,把Survivor无法保存的对象直接保存至老年代。

Minor GC 和 Full GC

上面一直提的Minor GC和Full GC两者主要是指的新生代GC (Minor GC) 和 老年代GC (Full GC)

  • Minor GC,指发生在新生代的垃圾收集动作,因为新生代的对象大多数存在时间不长所以Minor GC执行的非常频繁,当然速度也很快
  • Full GC,指发生在老年代的GC,一般说出现了Full GC 会伴随出现一次Minor GC,Full GC会比新生代的GC慢很多。

对象分配内存的图示

JVM学习——3.3 垃圾清理-内存分配_第1张图片

PS. 之前有些图示中会有PermGen(永久代)的存在,永久代主要保存类的静态变量、符号引用、字符串常量。而1.8之后,永久代已经被永久取消,取代的是Metaspace(元空间)其中类的静态变量被转移至JAVA堆中;符号引用,字符串常量被保存在元空间中。

你可能感兴趣的:(JAVA,#,JVM)