GC可达性分析回收算法 解决循环引用问题 强引用弱引用

JVM有一个回收算法是引用计数算法,每当对象被引用一次,就+1,释放一个引用就-1,当垃圾回收时,引用计数为0的对象就会被GC掉。但这个方法有个问题,就是无法解决循环引用的问题。

循环引用就是对象A引用了对象B,对象B引用了对象A,构成了一个引用环。彼此都没发挥什么作用,但却不会被GC。为了解决这个问题,就有了可达性分析回收算法。

可达性分析:

算法中定义了几个GC Root对象,这几个root对象在GC时不会被JVM回收掉,然后通过这些对象像树枝一样向外延伸,被引用到的对象说明还存活使用,就不会被GC,没有被这些root对象引用到的就会被GC掉。从而解决了循环引用问题。

Root对象主要包括:

①系统类加载器(bootstrap)加载的类。

②JVM方法区中静态属性引用的对象。

③JVM常量池中引用的对象。

④JVM虚拟机栈中引用的对象。

⑤JVM本地方法栈中引用的对象。

⑥活动着的线程。

官方解释:

GC roots

The so-called GC (Garbage Collector) roots are objects special for garbage collector. Garbage collector collects those objects that are not GC roots and are not accessible by references from GC roots.

There are several kinds of GC roots. One object can belong to more than one kind of root. The root kinds are:

  • Class - class loaded by system class loader. Such classes can never be unloaded. They can hold objects via static fields. Please note that classes loaded by custom class loaders are not roots, unless corresponding instances of java.lang.Class happen to be roots of other kind(s).
  • Thread - live thread
  • Stack Local - local variable or parameter of Java method
  • JNI Local - local variable or parameter of JNI method
  • JNI Global - global JNI reference
  • Monitor Used - objects used as a monitor for synchronization
  • Held by JVM - objects held from garbage collection by JVM for its purposes. Actually the list of such objects depends on JVM implementation. Possible known cases are: the system class loader, a few important exception classes which the JVM knows about, a few pre-allocated objects for exception handling, and custom class loaders when they are in the process of loading classes. Unfortunately, JVM provides absolutely no additional detail for such objects. Thus it is up to the analyst to decide to which case a certain "Held by JVM" belongs

强引用:

强引用就是引用了通过new 的方式创建的对象。在root搜索算法的里面,说的引用都指的是强引用关系。

Object obj = new Object();

obj这个变量引用了一个object对象,只有obj这个引用被释放了,对象才会被GC。

比如

obj=null;  

这样对象就会被释放。

软引用:

软引用的对象只有在内存不足的时候才会被回收掉,如果GC时,内存充足,那么软引用类型不会被回收。

软引用的作用是:软引用可用来实现内存敏感的高速缓存。如果内存充足,就可以一直把缓存放在内存中,加快数据访问速度。如果内存不足了,缓存就会被回收掉。

Object obj = new Object();
SoftReference<Object> softReference = new SoftReference<>(obj);

弱引用:

弱引用只会生存很短的时间,在第一次经历GC时,无论内存是否充足,都会被回收掉。

弱引用的作用就是:如果一个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么就可以将对象修饰为为弱引用类型。弱引用还可以用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。还有一种情况:当你想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个对象的生命周期,这时候就可以用弱引用。

Object obj = new Object();
WeakReference<Object> weakReference = new WeakReference(obj);

虚引用:

虚引用就是假的引用,如果一个对象与虚引用关联, 则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。虚引用必须配合引用队列使用。

虚引用的作用:因为虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时, 如果发现它还有虚引用,就会把这个虚引用加入到与之关联的引用队列中。所以程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。 如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

Object obj = new Object();
ReferenceQueue queue = new ReferenceQueue();
PhantomReference<Object> pf = new PhantomReference<Object>(obj,queue);

猜你喜欢

转载自blog.csdn.net/wanderlustLee/article/details/81291308