Java技术体系提倡的自动内存管理,最终,可以归结为自动化解决两个问题
- 给对象分配内存
回收分配给对象的内存
给对象分配内存,大方向上,是在堆上分配,但也可能经过JIT编译后,被拆散为标量类型,并间接地栈上分配
对象主要分配在新生代的Eden区域,如果启动了本地线程分配缓冲,将按线程,优先在Thread Local Allocation Buffer上分配。少数情况下,可能会直接分配到老年代。
具体取决于使用哪种垃圾收集器组合,还有配置参数
对象优先在 Eden 分配
大多数情况下,对象在新生代Eden区中分配,当Eden区没有足够空间分配时,虚拟机发生一次Minor GC
大对象直接进入老年代
-XX:PretenureSizeThreshold
长期存活对象进入老年代
-XX:MaxTenuringThreshold
Age计数器,如果Eden出生并经过第一次Minor GC 后存活,且能被Survior空间容纳,对象移动到Survivor,年龄+1
加到一定程度,默认是15,晋升到老年代
动态对象年龄判定
当Survivor中,相同年齡的对象大小,超过了Survivor空间的一半,这些年龄大于或等于这个年龄的对象,可以直接进入老年代
空间分配担保
新生代使用复制算法,当新生代出现大对象时,为保证能分配到空间,需要老年代的空间做担保,以便让大对象可以在新生代空间不足的情况下进入老年代,否则就只能Full GC
在Minor GC前,JVM 先检查老年代最大可用的连续空间是否大于 新生代所有对象的总和,
-如果大于,Minor GC可以确保安全
-如果小于,JVM会看HandlePromotionFailure设置值是否允許担保失败,
–如果允许,检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小
---如果大于,尝试Minor GC
---如果小于,Full GC
–如果不允许,Full GC