- 虚拟机遇到一个new指令的时候,首先检查这个指令的参数在常量池中关联的class信息是否存在,如果不存在先执行类加载过程。
- 如果class信息已经加载,会在堆内存中分配空间,对象所需的内存大小在类加载完成后便可以完全确定,分配方式可以分为指针碰撞和空闲列表,具体采用哪种分配方式是由java堆是否规整决定的,而java堆是否规整是由采集的垃圾回收机制是否有压缩整理功能决定的。即使分配内存考虑并发分配的情况,防止同一个内存被同时分配给两个对象,有两种解决方案:一种是对分配空间动作同步处理(cas+失败重试),一种是使用TLAB(Thread Local Allocation Buffer),每一个线程在java堆中预订一小块内存,等到分配完成后,才需要同步锁定,是否开启TLAB,是由虚拟机参数-XX:+/UseTLAB决定的。内存分配完成后,对new的对象进行初始化对象初始化链接。
- 对象优先在新生对分配,当Eden区没有足够的空间进行分配的时候,虚拟机将发起一次MinorGC,如果虚拟机认为对象已死(如何判断),将认为死亡的对象进行回收。如果对象无法回收(都是存活的),而存活的对象无法放入到Survivor空间,那么之后通过分配担保机制提前转移到老年代。如果对象过大,超过虚拟机配置,直接进入老年代,这样做的目的在于避免Eden区与两个Survivor区之间发生大量的内存复制(复制算法)。
- 对象在经历多次ygc之后,仍然没有被回收,超过虚拟机中的对象的年龄超过年龄阙值,对象进入老年代。老年代执行的是标记清除算法
以上都是个人的一些总结,如果有误,请不吝指教,谢谢。