关于java:面试官小伙子你给我简单讲一下垃圾回收机制如何工作的吧

7次阅读

共计 1733 个字符,预计需要花费 5 分钟才能阅读完成。

垃圾回收机制是什么?

垃圾回收是一种主动的存储管理机制。当一些被占用的内存不再须要时,就应该予以开释,以让出空间,这种存储资源管理,称为垃圾回收。

也就是说垃圾回收跟内存无关, 那么都有哪些内存呢

JVM 内存

JVM 将内存划分为五个区间.

JVM 分为五大内存空间, 其中程序计数器、虚拟机栈、本地办法栈 3 个区域随线程而生、随线程而灭,因而这几个区域的内存调配和回收都具备确定性,就不须要过多思考回收的问题,因为办法完结或者线程完结时,内存天然就跟随着回收了。而 Java 堆区和办法区则不一样,这部分内存的调配和回收是动静的,正是垃圾收集器所需关注的局部。

堆区的垃圾回收

什么是垃圾

如果一个对象曾经没有任何一个中央援用它, 它就是垃圾.

怎么确定是垃圾

援用计数法

给对象增加一个援用计数器,每当有一个中央援用它时,计数器加一。反之每当一个援用生效时,计数器减一。当计数器为 0 时,则示意对象不被援用。

可达性剖析

设立若干根对象(GC Root),每个对象都是一个子节点,当一个对象找不到根时,就认为该对象不可达。

触发条件

Minor GC 触发机制

当年老代满时就会触发 Minor GC,这里的年老代满指的是 Eden 代满,Survivor 满不会引发 GC。

FULL GC 触发机制

  1. 老年代空间有余
  2. 办法区空间有余
  3. 通过 Minor GC 后进入老年代的均匀大小大于老年代的可用内存。
  4. 由 Eden 区、From Survivor 区向 To Survivor 区复制时,对象大小大于 To Space 可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小.
  5. System.gc()办法的调用, 零碎倡议执行 Full GC,然而不必然执行.

回收算法

标记 - 革除算法

该算法先标记,后革除,遍历所有的 GC Root,别离标记处可达的对象和不可达的对象,而后将不可达的对象回收。

这种算法的有余次要体现在效率和空间

从效率的角度讲,标记和革除两个过程的效率都不高, 因为须要遍历所有 GC ROOT.

从空间的角度讲,标记革除后会产生大量不间断的内存碎片,内存碎片太多可能会导致当前程序运行过程中在须要调配较大对象时,无奈找到足够的间断内存而不得不提前触发一次垃圾收集动作。

复制算法

将内存分为两块,每次只应用一块。当这一块内存满了,就将还存活的对象复制到另一块上,并且严格依照内存地址排列,而后把已应用的那块内存对立回收。

长处是:解决了标记 - 革除算法的碎片问题, 可能失去间断的内存空间
毛病是:节约了一半内存

标记整顿算法

复制算法在对象存活率较高时, 继续复制效率非常低, 老年代都是不易被回收的对象, 针对老年代的特点, 能够采纳标记整顿算法, 标记整顿算法在标记 - 革除算法根底上, 它标记之后, 不间接清理, 是让所有存活对象都向一端挪动,而后间接清理掉边界以外的内存. 这样既防止了对象存活率较高时的继续复制, 也防止了内存碎片的呈现. 实用于老年代.

分代收集算法

古代商用虚拟机根本都采纳 分代收集算法 来进行垃圾回收。这种算法没什么特别之处,就是下面内容的联合.

它是对内存中的对象依照生命周期的长短, 以及所在区域的不同进行划分.

堆辨别为新生代, 老年代.

办法区为长久代.

新生代就是活不了多久就死亡的对象,个别在堆内存. 比方局部变量.

老年代是活的久但也会死亡的对象,个别在堆内存. 比方一些生命周期长的对象.

长久代是不死的对象,个别在办法区. 比方加载的 class 信息.

不同的年代应用不同的垃圾回收算法.

新生代应用复制算法.

老年代应用标记整顿算法.

办法区的垃圾回收

长久代也就是办法区,Java 虚拟机标准中说过能够不要求虚拟机在办法区实现垃圾收集,因为和堆区的垃圾回收效率相比,它的回收效率切实太低,然而此局部内存区域也是能够被回收的。

长久代和堆区的新生代和老年代不一样. 办法区次要回收的内容是废除常量和无用的类。

对于废除常量也可通过援用的可达性来判断,然而对于无用的类则须要同时满足上面 3 个条件:

  • 该类所有的实例都曾经被回收,也就是 Java 堆中不存在该类的任何实例;
  • 加载该类的 ClassLoader 曾经被回收;
  • 该类对应的 java.lang.Class 对象没有在任何中央被援用,无奈在任何中央通过 反射 拜访该类的办法。.

最初

大家看完有什么不懂的能够在评论区问我,感觉对你有帮忙的话记得给我点个赞谢谢!

正文完
 0