java垃圾回收机制

2 篇文章 0 订阅
1 篇文章 0 订阅

      Java内存结构分为:程序计数器、虚拟机栈、本地方法栈、堆、方法区,这个5个区域。程序计数器、虚拟机栈和本地方法栈随着线程而生,随着线程而灭。所以Java垃圾回收主要针对的是堆和方法区这两个内存,在jdk8版本后方法区(永久代)又被取消,所以Java垃圾回收主要针对堆内存。下面就如下的三个问题展开了解java垃圾回收机制。

一、哪些对象需要回收

      程序在运行时,创建的所有的对象都在堆分配内存,所以Java回收的主要的就是无用的死掉的Java对象。那什么是无用的死掉的Java对象呢,jvm是怎么判定对象已死的。Java是通过可达性分析算法判定对象是否存活,下面来介绍一下可达性分析算法:
把一些对象作为根对象“GC roots”,从这些根对象向下枚举,和这些对象没有任何关联的对象判定为不可达对象,则证明这些对象不再被引用,那么判定这些对象已死。如下图:没有和GC_Root对象有引用关系的,则认为对象可回收。
在这里插入图片描述

那么什么是GC_Root对象呢,jvm规定如下几种:
       1.虚拟机栈(栈帧中的本地变量表)中引用的对象
       2.方法区中静态属性引用的对象
       3.方法区中常量引用的对象
       4.本地方法栈中JNI(即Native方法)引用的对象



二、如何回收
2.1 分代理论

      在回收对象之前,Jvm提出一个重要理论:分代理论。由大量实验数据表明,Java应用程序中,大量对象都是朝生夕灭的,又有一部分对象是经过很多次的垃圾回收,他们的引用依然存在的,也就是在整个Java应用过程中,会保持很长时间引用甚至整个程序的运行中,Java针对不用的对象,依据对象年龄(熬过垃圾回收的次数),就将Java堆分为了新生代(Minor GC)和老年代(Major GC);针对不用代有不同的回收算法应用。
新生代(Minor GC):新生代中每次发现有大批对象死去
老年代(Major GC):每次回收后存活的少量对象,将会逐步晋升到老年代中存放。



2.2 回收算法

有如下三种算法实现:
1.标记-清除算法:先标记上需要被回收的对象,然后对标记的对象清楚;
优点:简单高效;
缺点:清除后的堆内存,会造成大量的内存碎片,使内存不连续,为后续的新对象有内存也很难分配。
应用:一般用在老年代。新生代有大量的对象死去,因此需要大量的标记和清除动作,大大降低效率;新生代被清楚后空间碎片太多。而老年代则恰好相反,只有少数对象需要标记清除,遗留很少的碎片空间。

在这里插入图片描述


2.标记-复制算法:在标记清除算法之上的改进,在内存上划分两片区域,每次使用其中的一半,等到使用的一半内存不足时,将回收的对象清除,剩余存活的对象复制到另一半,周而复始。
优点:实现简单,运行高效,解决了内存碎片问题
缺点:内存太浪费,一直有一半内存属于无用状态
应用:应用于新生代。由于新生代大量对象清除,只需复制少数的存活对象到另一半区域。而老年代则反之,老年代有大量的存活对象需要复制,大大降低效率。
在这里插入图片描述


3.标记-整理算法:也是在标记清楚算法基础上,也是标记清除死亡对象,但和标记复制算法不同的是,对于存活对象不像标记复制算法复制到另一半区域,整理算法是将存活的对象全部向一边移动。
优点:解决了内存浪费的问题;
缺点:如果大量的对象存活,需要对大量对象移动,那么就需要改变对象的引用地址。应用地址的改变而且需要暂停用户线程。
应用:老年代。针对标记清除算法遗留的空间碎片问题,提出整理算法来解决该问题。
在这里插入图片描述




三、什么时候回收

      对于以上复制算法在新生代的应用,还有一个问题:内存浪费,一直有一半的内存空间属于无用状态。针对新生代“朝生夕灭”的特点(新生代中的对象98%熬不过第一轮收集),对此部分垃圾收集器(以上算法只是思想,垃圾收集器是对算法的落地实现)进一步优化,将原来的1:1空间将新生代划分为:一个Eden和两个Survivor,所占内存比例是8:1:1。如下图:
在这里插入图片描述
      每次为新new的对象分配内存时,优先选择Eden区和其中的一个Survivor,当这两个区域快要满时,则进行Minor GC新生代收集,将存活的对象复制到另一个Survivor中,被复制过来的对象,年龄加1。经过如此反复的收集过程,当存在于Survivor中的对象年龄到达15时,下一次的收集还是存活,会被复制到老年代。
      并不是所有的对象都经过15次收集才会到老年代,对于一些大对象会直接分配到老年代。最典型的大对象指很长的字符串,或者元素数量很大的数组。大对象应该在程序中避免,原因是给大对象分配空间时,导致内存中还有不少的空间时,就提前导致垃圾收集动作,以获取足够的连续空间来安置他们,当复制大对象那个时,更消耗内存和空间。虚拟机提供-XX:PretenureSizeThreshold参数,指定大于该设置值的对象直接在老年代分配。
      也并不是所有的对象都要经过15次收集才会到老年代,对象晋升到老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold设置。当对象年龄到达该设置值时,会被复制到老年代。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值