对象回收:

如果一个对象从”gc root set“登程,无奈达到,那么这个对象即能够被认为能够被回收。这里root set在不同垃圾回收器、不同区域的gc体现不同。如应用cms gc,

在yang gc的时候,root set蕴含:

虚拟机栈中援用的对象:虚拟机栈中的援用的对象能够作为GC Root。咱们程序在虚拟机的栈中执行,每次函数调用调用都是一次入栈。在栈中包含局部变量表和操作数栈,局部变量表中的变量可能为援用类型(reference),他们援用的对象即可作为GC Root。不过随着函数调用完结出栈,这些援用便会隐没。
办法区中类动态属性援用的对象:简略的说就是咱们在类中应用的static申明的援用类型字段
办法区中常量援用的对象:简略的说就是咱们在类中应用final申明的援用类型字段
本地办法栈中援用的对象
在cms gc的时候,root set蕴含:除了以上的,还包含年老代的对象(无论死活)、包含cms gc期间降职的对象。

四种援用

强援用:咱们个别创建对象的时候应用的都是强援用,强援用只有存在,对象就不会被gc回收,哪怕空间不够抛出oom。
软援用是用来形容一些非必须但仍有用的对象。在内存足够的时候,软援用对象不会被回收,只有在内存不足时,零碎则会回收软援用对象,在零碎将要产生内存溢出异样之前,将会把这些对象列进回收范畴进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异样。。这种个性经常被用来实现缓存技术。
弱援用的援用强度比软援用要更弱一些,无论内存是否足够,只有 JVM 开始进行垃圾回收,那些被弱援用关联的对象都会被回收。用来帮忙gc回收,当对象的强援用存在时,能够通过弱援用拜访这个对象,当强援用不存在时,帮忙gc回收。比方ThreadLocal的实现
虚援用是最弱的一种援用关系,如果一个对象仅持有虚援用,那么它就和没有任何援用一样,它随时可能会被回收,用 PhantomReference 类来示意,任何时候调用它的 get() 办法都是返回一个null,也就是说将永远无奈通过虚援用来获取对象,虚援用必须要和 ReferenceQueue 援用队列一起应用。在对象被回收时,会将虚援用退出队列,能够通过判断援用队列中是否曾经退出了援用,来判断被援用的对象是否将要被垃圾回收,这样就能够在对象被回收之前采取一些必要的措施。如间接内存回收的实现。

非强援用对象回收机会:如果一个对象只有非强援用指向,什么时候回收?

软援用对象回收的机会:

clock 上次产生垃圾回收的工夫戳,由垃圾回收器更新,全局共享
timestamp 该软援用最初一次被获取的工夫, 公有.
从这两个属性可得从上次gc起某个软援用未被拜访的工夫 idletime(可能为负值)
idletime = clock - timestamp
同时咱们有软援用闲暇保留工夫(全局) idlelivetime
idlelivetime = 堆中残余内存 (MB)* 每MB闲暇内存保留工夫
每MB闲暇内存保留工夫对应JVM参数 -XX:SoftRefLRUPolicyMSPerMB
当须要对软援用进行回收时,idletime大于 idlelivetime的软援用会被回收.

在内存不足时,零碎则会回收软援用对象,在零碎将要产生内存溢出异样之前,将会把这些对象列进回收范畴进行第二次回收
弱援用对象回收的机会:

只有 JVM 开始进行垃圾回收,那些被弱援用关联的对象都会被回收。

虚援用对象回收的机会:

虚援用必须配合队列应用,在jdk8及以前,虚援用对象要被回收必须将虚援用自身回收掉,也就是说虚援用对象被jdk回收时,必须解决虚援用,不然空间不会开释。jdk9批改设计。
非凡阐明:非强援用的解决都是jvm后盾线程异步解决的,这些线程优先级并不高,也就是说gc流动完结时,这些对象并不一定立马回收了,如果应用程序对象创立频繁,可能触发fullgc。full gc会stw。

类卸载的机会

  1. 该类所有的实例曾经被回收
  2. 加载该类的ClassLoder曾经被回收
  3. 该类对应的java.lang.Class对象没有任何对方被援用
    元空间的gc:

当元空间不够的时候扩容,当扩容到metadataSize的时候会触发一次old gc,当扩容到maxMedataSize的时候,会触发一次full gc。

间接内存开释:

间接内存的开释是由cleaner实现的,cleaner继承虚援用,当间接内存的强援用回收掉时,jvm后盾解决援用的线程就会调用cleaner的clean办法,最终通过free开释空间。当间接内存的对象降职到了老年代,那么在产生old gc之前,这一块间接内存都不会开释,造成内存透露。