java的堆内存能够类比于计算机的内存,是存储整个机器数据的地方。java
(1)jvm一块儿动就建立java堆。类比计算机一块儿动就加载内存。算法
(2)全部的线程共享。类比计算机全部进程共享一个内存。jvm
(3)是存放实例对象的地方。线程
主要分为年轻代(占堆内存1/3)和老年代(占堆内存2/3)。年轻代又分为eden(占年轻代8/10),from(占年轻代1/10),to(占年轻代1/10)。下面开始分别介绍。对象
老年代:存储大对象和一些生命周期长的对象。blog
年轻代:存储占内存少而且生命周期短的对象。生命周期
那么问题来了,对象的大小比较好说,直接比较占的空间就行;生命周期长短,这玩意怎么算呢?这就是下面要介绍的eden,from,to进程
一个对象被new出来以后,是在eden中的。而new对象的操做很频繁,new的对象多了,eden装不下了,就须要对eden进行gc(垃圾回收),发生在eden中的这种小级别的gc叫作minor gc。内存
先介绍一下eden,from,to垃圾回收
eden:对象出生的地方
from:保存幸存数据的地方
to:空的幸存区
minor gc的过程以下:(参考上图红色的标线)
(1)把eden中活着的对象放到to中,并标记年龄为1。(有一部分可能会被垃圾回收掉)
(2)把from中的活着的对象 age+1(有一部分可能会被垃圾回收掉)。若是age达到阈值(默认15岁),就直接放到老年代中;若是age未达到阈值,就放到to中。
(3)通过步骤(2),to里面保存了存活的对象,from反而清空了。这时候将from和to进行标记切换,from变to,to变from。(备注:当to满了的时候,直接将to里面的数据所有放入老年代)
总结:
minor gc使用复制删除算法,能减小空间碎片。
全部的Minor GC都会中止应用程序的全部线程,不过这个过程很是短暂。
采用的是标记-清除算法。
老年代的对象都是程序认为生命力比较顽强的,不是那么容易死掉的,因此不必频繁的进行full gc。并且老年代的数据比新生代多的多,执行起来也比较耗时。
由于标记清除算法的弊端,会形成不少的内存碎片,当一个大对象进来,没有足够存储他的连续空间的时候,就会执行Full gc。执行完以后就有足够且连续的空间来存放新的对象了。