jvm

 

 

https://www.jianshu.com/p/9885ac7eac98

这是在面试中碰到的问题,现在做一下总结:

面试题:对象进入堆内存中,怎么从Eden区转入Survivor区,过程是怎么样的?新生代的内存为什么这么分配?

首先讲这问题大部分资料讲的都不是很明确,这里也只是对大致过程做一些整理。

一、对象的回收过程

Java堆内存的空间分配如图:

 
堆内存分配

新生代的内存分配说明:

Eden:主要是存放新增的对象,由于Eden区的对象都有一个特点,就是生命周期比较短,所以在每一次的GC都会将保存的对象清理回收。Eden区经历一次gc会清理掉大量的对象,如果此时存活的对象很多,而且大于Survivor区能公接收的范围,这些对象就会进入老年代。反之进入To Survivor区,minorGC完成之后,To 与 From完成角色互换,此时的To Survivor区变成下一次的From Survivor区。

From/To : 存放经历gc存活的对象,在这两块内存区域的对象也不是会一直存活,VM为每个对象设定了一个年龄,进入Survivor区对象的年龄变为1,此后每经历一次GC,年龄就会增加1,到达设定的年龄阈值(-XX:MaxTenuringThreshold,默认15),对象就会进入老年代,如果相同年龄的对象占用内存超过Survivor区内存的一半也会直接进入老年代。

到此回答完了面试问题。下面做一些问题的扩展,对象回收的判定,回收算法,垃圾回收器等


二、对象的回收判断:

1、引用计数法:给每个对象添加一个引用计数器,每当有一个对象引用它,计数器增加1,引用失效时计数器减1。任何时刻计数器为0就判定位没有对象引用。实际的VM回收过程中,并没有按照引用计数法判断对象是否存活。

2、可达性分析算法:Java是根据该算法判定对象的回收。基本思路:每个对象的创建都是以GC Root作为对象的起点,每发生一次对象引用,就会往引用链中增加一个对象,根对象结束了生命周期,引用的对象就没有GC Root,当发生GC时,这些没用根对象的引用就会被回收。

三、垃圾回收算法:

标记清除:

分为两个阶段,标记,清除,被标记的对象会在标记结束有被清除回收。但由于回收的对象是分散的,所以就会导致内存碎片化严重。

复制算法:

将内存分为容量大小相等的两块,当发生GC之后,将from的对象,复制到to区,避免了内存碎片,但也造成空间浪费。

标记整理:

标记完存活的对象之后,将存活的对象集中存放。

分代收集:

按照对象的特性区分年轻代,老年代,根据对象的特性选择对应的回收算法。年轻代,存活时间短选择复制算法,老年代选择标记清除或标记整理。

四、垃圾回收器:

 
新生代回收器

 

 
老年代回收器

五、JVM的内存分配

JVM运行时的内存分配:

线程私有:

程序计数器(指示当前指令地址)、Java栈(运行出入口方法信息)、本地方法区(native方法)

线程共享:堆,方法区(包含运行常量池,保存VM加载的类的信息,常量,静态变量)

 
运行时内存

在对JVM进行参数调优,对垃圾回收器的调整比较少,一般是对内存分配进行跳转,下图是内存分配的参数示意图。

 
JVM参数分配




posted @ 2019-10-30 15:20  薄情的树先生  阅读(113)  评论(0编辑  收藏  举报