jvm内存:
分为栈,堆,方法区。
堆内存是所有线程共享的内存区域:存储了所有的对象实例,数组对象,静态对象。为了便于jvm垃圾回收,将堆内存分为新生代和年老代。
新生代:分配对象首先分配在新生代。
新生代对象的特点:生命周期短,存活时间低。
新生代垃圾回收:minor gc 发生频繁,采用复制算法来进行垃圾回收。
复制算法:新生代内存区域被分为两块:在分配对象的时候首先在一块区域分配,当出现gc时,会将存活的的对象直接复制到另外一块内存区域,之后清理上一块内存区域。
反映到jvm上就是:新生代分为一个eden区域,两个survior区域,默认比例是8:1,分配对象优先分配在eden区,当内存不足以分配新对象时,触发minor gc,会将eden中存活的对象直接转移到survior中的to区,survior中的from区中对象年龄达到年老代阈值时,转移到年老代,否则转移到to区,这样from中内存就没有在使用,from和to互换角色,承担对方的职责。
年老代:存活时间长的对象。
特点:对象一般较大,且存活时间长。
垃圾回收:major gc 至少伴随着一次minor gc 所以也叫做 full gc,年老代采用标记清除,或者是标记整理算法。
标记清除:将需要回收的对象标记,之后清除,存在效率问题,且存在大量的空间碎片,当年老代控件不足时,提前触发full gc。
标记整理:弥补了上面的缺点,会将内存空间整理成连续的空间。
(1)对象优先分配在eden区
(2)大对象直接分配在年老区 (大对象指数组这类对象)
(3)长期存活的对象直接进入年老代
(4)若survior中存活的对象的大小超过survior的一半,那么内存占用大于等于该内存的对象直接进入年老代
(5)空间分配担保:若eden区无法分配对象,请求在年老代直接分配对象,但存在风险,若年老代空间不足,会提前触发full gc。
尽量避免full gc 因为full gc 伴随着的stop the word 即暂停所有的线程,且full gc时间较长,容易导致长时间服务器没有响应。