从0到1理解JVM内存分配机制

在JAVA中,除了在即时编译器优化后部分对象会在栈上分得足够空间,其余的对象都会在堆上“求分配空间”,所以之前我们才说,堆里存在着大大小小密密麻麻的对象

那么在堆里,对象究竟会分到哪部分的内存,新生代还是老年代?

普通对象

答案是:对象一般会分配到新生代中Eden区的内存。

一个普通对象的极端经历

有新对象到来,而Eden又没有足够的空间时,新生代尝试进行新生代的垃圾回收(也就是Minor GC)。在尝试之前,它需要知道,如果情况特别糟糕,这次Minor GC是否安全,也就是新生代所有对象都必须移到老年代以便腾出空间存放新对象,换句话说,新生代会问老年代:“你还有连续空间可以存放我现在的崽崽们吗”,如果老年代给他个肯定,新生代就可以无忧无虑地进行Minor GC了。

如果老年代没有给出肯定答案,新生代就会再问一句:“在以往迁往你那边的对象大小里,取个平均值,你现在还有那么大的连续空间吗?”如果老年代回答yes,新生代就认为接下来的Minor GC的对象有极大的可能小于历史平均值,可以冒些风险进行MinorGC(风险是接下来的对象确实超过了历史平均值,老年代没有连续空间存放新生代来的对象,老年代需要进行老年代的回收也就是Full GC,因为新生代的冒险进行了一次失败的Minor GC,老年代需付出Full GC的代价,而后新生代再重头尝试Minor GC)。当然了,如果老年代说了不,那么新生代就得先等老年代执行了Full GC再执行新生代专属的Minor GC。

那些超大的对象

如果对象十分非常极其以及特别的巨大,那么新生代会直接请求老年代的帮助,将对象分配在老年代(老年代人太好了,新生代装不下的对象它负责装。)

一群长寿的对象

如果对象太老,也就是说在Eden区呆了一代,又在Survivor存活期呆了15代(默认是15代),那么该对象会迁往老年代,可见,JVM的世界里,一个对象的退休年龄是16。

一群稳定的幸存者

Survivor区中的对象不必等15代才能迁往老年代。如果某一年纪的对象的所占空间超过Survivor区大小的一半,它们会被赶走,赶到老年代。那种年纪的对象有这么多一起存活了这么长时间,JVM默认它们这一代的稳定性都比较好,可以提前去老年区过稳定的生活。