内存的分配:
1)指针碰撞(bump the pointer):适用于内存整齐的情况,已使用的在一边,未使用的在一边。
新生代对象的内存分配
2)空闲列表(free list):内存中已分配和未分配的内存互相交错,用链表记录空闲内存块。
老年代对象的内存分配
多线程分配可能导致分配不安全,有以下策略:
1)CAS分配(失败-重试策略)
2)(本地化)TLAB:Thread Local Allacation Buffer:本地线程分配缓冲区,为线程预先分配一块内存。
哪些内存需要回收?
程序计数器,JVM方法栈,本地方法栈所占用的内存的回收都有确定性,所以内存回收主要指的是堆和元空间(JDK8以前是方法区)
什么样的对象需要回收?
死掉的对象。判断对象的生死一般有两种算法:
1)引用计数算法:缺点是不能解决循环引用的问题
2)可达性算法:根对象所不能到达的对象。常见的根对象有:栈帧中引用的对象,常量等。
对象的引用
1)强引用:永远不会被回收
2)软引用:内存紧张的时候会被回收
3)弱引用:GC时一定会被回收
4)虚引用:无法通过虚引用得到一个实例
废弃的常量和类也需要回收。
对象的内存分配需要一块连续内存。
对象优先在堆中新生代中的Eden区分配,如果空间不够,将触发Minor GC。
分配担保:如果老年代的连续空间大于新生代对象总和或历次晋升平均值,那么将触发Minor GC,否则触发Full GC。一般Full GC比Minor GC慢10倍以上。
长期存活的新生代对象会进入老年代
年龄计数器:每经历一次MinorGC,计数器加1,到了一定年龄会晋升到老年代。
动态年龄:如果某年龄的对象大于新生代一般,那么大于等于这个年龄的对象都会晋升到老年代。
如果对象大于某阈值(-XX:PretenureSizeThreshold),那么直接在老年代分配空间。
新生代和老年代是什么关系?
老年代为新生代提供分配担保。
新生代中存活的对象将存放在老年代中的,但这带来一个问题:老年代是否有足够的空间存放晋升而来的对象呢?
当新生代不足以为新对象分配空间时,触发Minor GC,在此之前JVM会检查老年代最大可用连续空间是否大于新生代所有对象 或者 历次晋升到老年代对象的平均大小,如果成立则进行Minor GC,否则将进行Full GC。
网友评论