赞
踩
为了让程序员更加专注于代码的实现,而不用过多的考虑内存释放的问题,所以在Java语言中,有了自动的垃圾回收机制,也是我们常常提及的GC(Garbage Collection)
有了这个垃圾回收机制之后,程序员只需要考虑内存的申请即可,内存的释放由系统自动识别完成。在垃圾回收的时候,不同的对象引用类型,GC会采用不同的回收时机,换句话说自动垃圾回收算法就会变得非常重要,如果因为算法的不合理,导致内存资源一直没有释放,同样也可能导致内存资源一直没有被释放,同样也可能会导致内存溢出
简单用一句话来说:人如果一个或者多个对象没有任何的引用指向它,那么这个对象现在就是垃圾,如果定位成垃圾,那么就有可能被垃圾回收器回收
如果要定位什么是垃圾,有两种方式来确定,第一个是引用计数法,第二个是可达性分析算法
一个对象被引用一次,在当前对象头上递增一次引用次数 ,如果这个对象的引用次数为0,代表这个对象可以被回收
String demo = new String("123");
String demo = null;
当对象间出现了循环引用的话,则引用计数法就会失效,如下图:
虽然a和b都为null,但是由于a和b存在循环引用,这样a和b永远都不会被回收
引用计数法的优点:
缺点:
现在的虚拟机采用的都是通过可达性分析算法来确定哪些内容是垃圾
首先会存在一个根节点(GC Roots),引出它下面指向的下一个节点,在以下一个节点开始为开始找到它下面的节点,依次往下类推,直到所有节点全部遍历完毕。这个思想类似于算法中的并查集
如上图,X和Y就是GC Roots无法到达的节点,那么X和Y就可以被认为是垃圾
根对象是那些肯定不能当作垃圾回收的对象,就可以当作根对象。一般有四种类型可以选做根对象:
刚刚已经讲解完了如何定义垃圾,那么定义完成之后的垃圾有一系列的处理算法
标记清除算法,是将垃圾回收分为两个阶段,分别是标记和清除
标记清除算法有一定的劣势:
复制算法的核心就是,将原来的内存空间一分为二,每次都是用其中的一块内存。在垃圾回收的时候,将正在使用的对象复制到另一个内存空间中,然后将该内存空间清空,交换两个内存的角色,完成垃圾的
如果内存中的垃圾对象较多,需要复制的对象就较少,这种情况下适合使用该 方式并且效率比较高,反之,则不适合
复制算法的执行流程:
优点:
缺点:
标记整理算法是在标记清除算法的基础上,做了优化和改进的算法。和标记清除算法一样,也是从根节点开始,对对象的引用进行标记,在清理阶段,并不是简单的直接清理可回收对象,而是将存活对象都向内存的另一端移动,让然后清理边界以外的垃圾,从而解决了碎片化的问题
标记整理算法的执行流程:
优缺点:
在Java8时,堆被分成两份新生代和老年代(1:2),在Java7的时候,还存在一个永久代,Java8将其移动到本地内存的元空间中
对于新生代,内部被分为三个区域:Eden区,两个大小完全相同的survivor区S0(from)和S1(to)(8:1:1)
分代收集算法执行流程:
MinorGC 、 Mixed GC 、 FullGC 的区别是什么
在JVM中,实现了多种垃圾收集器,包括:
Serial和Serial Old串行垃圾收集器,是指使用单线程进行垃圾回收,堆内存较小,适合个人电脑
垃圾回收时,只有一个线程在工作,并且Java应用中所有线程都要暂停(STW),等待垃圾回收的完成
Parallel New和Parallel Old是一个并行垃圾回收器,JDK8默认使用此垃圾回收器
垃圾回收时,多个线程在工作,并且java应用中的所有线程都要暂停(STW), 等待垃圾回收的完成
CMS全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,该回收器是针对老年代垃圾回收的,是一款以获取最短回收停顿时间为目标的收集器,停顿时间短,用户体验就好。其最大特点是在进行垃圾回收时,应用仍然能正常运行
应用于新生代和老年代,在JDK9之后默认人使用的G1垃圾收集器。其中划分了很多个区域,每个区域都可以充当eden,survivor,old,humongous,其中humongous专门为大对象准备的。采用的复制算法,并且注重于响应时间和吞吐量。运行时主要是分为三个阶段:新生代回收、并发标记、混合收集。如果出现并发失败(即回收速度赶不上创建新对象的速度),就会触发Full GC
下面来详细的讲解一下年轻代垃圾回收:
下面来说一下下一个阶段年轻代垃圾回收 + 并发标记:
混合垃圾回收的执行流程:
复制完成,内存得到释放。进入到下一轮的新生代回收、并发标记、混合收集
其中H叫做大对象,如果对象非常大,就会开辟一块连续的空间存储巨型对象
强引用:只有所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能 被垃圾回收
User user = new User()
软引用:仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次出发垃圾回收
- User user = new User();
- SoftReference softReference = new SoftReference(user);
弱引用:仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
- User user = new User();
- WeakReference weakReference = new WeakReference(user);
虚引用:必须配合引用队列使用,被引用对象回收时,会将虚引用入队,由Reference Handler线程调用虚引用相关方法释放直接内存
- User user = new User();
- ReferenceQueue referenceQueue = new ReferenceQueue();
- PhantomReference phantomReference = new PhantomReference(user,queue);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。