JVM-堆内存

1. java堆内存介绍

java的堆内存可以类比于计算机的内存,是存储整个机器数据的地方。

(1)jvm一起动就创建java堆。类比计算机一起动就加载内存。

(2)所有的线程共享。类比计算机所有进程共享一个内存。

(3)是存放实例对象的地方。

 

2. 堆内存图示

JVM-堆内存

 

 

 

3. 堆内存划分

主要分为年轻代(占堆内存1/3)和老年代(占堆内存2/3)。年轻代又分为eden(占年轻代8/10),from(占年轻代1/10),to(占年轻代1/10)。下面开始分别介绍。

老年代:存储大对象和一些生命周期长的对象。

年轻代:存储占内存少并且生命周期短的对象。

 

那么问题来了,对象的大小比较好说,直接比较占的空间就行;生命周期长短,这玩意怎么算呢?这就是下面要介绍的eden,from,to

一个对象被new出来之后,是在eden中的。而new对象的操作很频繁,new的对象多了,eden装不下了,就需要对eden进行gc(垃圾回收),发生在eden中的这种小级别的gc叫做minor gc。

 

4. minor gc(young 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都会停止应用程序的所有线程,不过这个过程非常短暂。

 

5. major gc(full gc)

采用的是标记-清除算法。

老年代的对象都是程序认为生命力比较顽强的,不是那么容易死掉的,所以没必要频繁的进行full gc。而且老年代的数据比新生代多的多,执行起来也比较耗时。

因为标记清除算法的弊端,会造成很多的内存碎片,当一个大对象进来,没有足够存储他的连续空间的时候,就会执行Full gc。执行完之后就有足够且连续的空间来存放新的对象了。

 

上一篇:面试【JAVA基础】JVM


下一篇:为什么新生代内存需要有两个Survivor区