jdk源码解析--Finalizer类

Posted 我的IT技术路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdk源码解析--Finalizer类相关的知识,希望对你有一定的参考价值。

在之前几篇内容中,我们介绍了java几种引用,并深入解释软引用和弱引用的功能,通过引用缓存来说明了这两个引用在实际中的作用。本文我们将介绍java引用的最后一点内容FinalizerFinalizer这个在实际上也不常使用,不过在面试的时候会经常被问到Finalizerfinally的关系。说实在的,这两个根本没啥关系呀,Finalizerjvm内存内容中的一个实现类,而finallyjava的一个关键字,该关键字一般在异常捕获中使用,一般常和try/catch等联合使用。Finally之前在java关键字的介绍的时候有提到到,本文中点讲述一下Finalizer类的实现和使用。

首先明确一下:Finalizer类的作用是什么?Finalizer是一个类清除时候的一些资源清理收尾工作,它一般在适当的时候被JVM调用。在effect java中明确有一点说明Finalizer方法:避免使用终结方法和清除方法。终结方法就是本文说的Finalizer方法,清除方法是java9中实现的用来替换java8 的终结方法。虽然 java9希望清除对象时没那么危险,但是依然是不希望被使用的。终结方法的使用有以下几个问题:

1) 行为的不稳定

2) 降低性能

3) 可移植性问题

以上的说明只想告诉读者,在一般情况下不要使用终结方法,但这并不影响我们看下这个类的源码是怎么实现的,如下为实现的类图。

 

我们先看下其父类的实现,就一个构造函数,jdk明确表示该类就是为了实现Finalizer类的:

1. class FinalReference<T> extends Reference<T> {  

2.   

3.     public FinalReference(T referent, ReferenceQueue<? super T> q) {  

4.         super(referent, q);  

5.     }  

6. }  

Finalizer类的代码:

1. final class Finalizer extends FinalReference<Object> { //常量  

2.   

3.     private static ReferenceQueue<Object> queue = new ReferenceQueue<>();//定义一个引用队列  

4.     private static Finalizer unfinalized = null;//定义一个未初始化的类  

5.     private static final Object lock = new Object();//锁对象  

6.   

7.     private Finalizer  

8.         next = null,//常引用队列的前一个  

9.         prev = null;//常引用队列的后一个  

10.   

11.     private boolean hasBeenFinalized() {//是否初始化  

12.         return (next == this);  

13.     }  

14.   

15.     private void add() {//添加当前元素到常量队列中  

16.         synchronized (lock) {//加锁  

17.             if (unfinalized != null) {  

18.                 this.next = unfinalized;  

19.                 unfinalized.prev = this;  

20.             }  

21.             unfinalized = this;  

22.         }  

23.     }  

24.   

25.     private void remove() {//删除常量队列中当前元素  

26.         synchronized (lock) {  

27.             if (unfinalized == this) {  

28.                 if (this.next != null) {  

29.                     unfinalized = this.next;  

30.                 } else {  

31.                     unfinalized = this.prev;  

32.                 }  

33.             }  

34.             if (this.next != null) {  

35.                 this.next.prev = this.prev;  

36.             }  

37.             if (this.prev != null) {  

38.                 this.prev.next = this.next;  

39.             }  

40.             this.next = this;   //确保当前被初始化  

41.             this.prev = this;  

42.         }  

43.     }  

44.   

45.     private Finalizer(Object finalizee) {//构造函数,传入对象  

46.         super(finalizee, queue);  

47.         add();//添加到序列中  

48.     }  

49.   

50.     /* Invoked by VM */  

51.     static void register(Object finalizee) {//注册到jvm中  

52.         new Finalizer(finalizee);  

53.     }  

54.   

55.     private void runFinalizer(JavaLangAccess jla) {  

56.         synchronized (this) {//加锁,this锁  

57.             if (hasBeenFinalized()) return;//已经初始化的直接返回  

58.             remove();//否则删除  

59.         }  

60.         try {  

61.             Object finalizee = this.get();  

62.             if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {  

63.                 jla.invokeFinalize(finalizee);//执行终结方法  

64.   

65.                 /* Clear stack slot containing this variable, to decrease 

66.                    the chances of false retention with a conservative GC */  

67.                 finalizee = null;  

68.             }  

69.         } catch (Throwable x) { }  

70.         super.clear();  

71.     }  

72.   

73.      

74.     private static void forkSecondaryFinalizer(final Runnable proc) {//创建另一个特殊功能辅助终结器,该方法被runFinalization 和 runFinalizersOnExit调用  

75.         AccessController.doPrivileged(  

76.             new PrivilegedAction<Void>() {  

77.                 public Void run() {  

78.                 ThreadGroup tg = Thread.currentThread().getThreadGroup();  

79.                 for (ThreadGroup tgn = tg;  

80.                      tgn != null;  

81.                      tg = tgn, tgn = tg.getParent());  

82.                 Thread sft = new Thread(tg, proc, "Secondary finalizer");  

83.                 sft.start();  

84.                 try {  

85.                     sft.join();//等待  

86.                 } catch (InterruptedException x) {  

87.                     /* Ignore */  

88.                 }  

89.                 return null;  

90.                 }});  

91.     }  

92.   

93.     /* Called by Runtime.runFinalization() */  

94.     static void runFinalization() {//虚拟机执行  

95.         if (!VM.isBooted()) {  

96.             return;  

97.         }  

98.   

99.         forkSecondaryFinalizer(new Runnable() {  

100.             private volatile boolean running;  

101.             public void run() {  

102.                 if (running)  

103.                     return;  

104.                 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();  

105.                 running = true;  

106.                 for (;;) {  

107.                     Finalizer f = (Finalizer)queue.poll();  

108.                     if (f == nullbreak;  

109.                     f.runFinalizer(jla);  

110.                 }  

111.             }  

112.         });  

113.     }  

114.   

115.     /* Invoked by java.lang.Shutdown */  

116.     static void runAllFinalizers() {//java虚拟机要关闭的时候,  

117.         if (!VM.isBooted()) {  

118.             return;  

119.         }  

120.   

121.         forkSecondaryFinalizer(new Runnable() {  

122.             private volatile boolean running;  

123.             public void run() {  

124.                 if (running)  

125.                     return;  

126.                 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();  

127.                 running = true;  

128.                 for (;;) {  

129.                     Finalizer f;  

130.                     synchronized (lock) {  

131.                         f = unfinalized;  

132.                         if (f == nullbreak;  

133.                         unfinalized = f.next;  

134.                     }  

135.                     f.runFinalizer(jla);//依次执行删除方法  

136.                 }}});  

137.     }  

138.   

139.     private static class FinalizerThread extends Thread {  

140.         private volatile boolean running;//是否运行,使用volatile保证可见性  

141.         FinalizerThread(ThreadGroup g) {  

142.             super(g, "Finalizer");  

143.         }  

144.         public void run() {  

145.             if (running)  

146.                 return;  

147.   

148.             // Finalizer thread starts before System.initializeSystemClass  

149.             // is called.  Wait until JavaLangAccess is available  

150.             while (!VM.isBooted()) {//如果jvm还没启动,等待  

151.                 // delay until VM completes initialization  

152.                 try {  

153.                     VM.awaitBooted();  

154.                 } catch (InterruptedException x) {  

155.                     // ignore and continue  

156.                 }  

157.             }  

158.             final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();//获取  

159.             running = true;  

160.             for (;;) {  

161.                 try {  

162.                     Finalizer f = (Finalizer)queue.remove();//移除队列的元素  

163.                     f.runFinalizer(jla);//执行终结的方法  

164.                 } catch (InterruptedException x) {  

165.                     // ignore and continue  

166.                 }  

167.             }  

168.         }  

169.     }  

170.   

171.     static {  

172.         ThreadGroup tg = Thread.currentThread().getThreadGroup();  

173.         for (ThreadGroup tgn = tg;  

174.              tgn != null;  

175.              tg = tgn, tgn = tg.getParent());  

176.         Thread finalizer = new FinalizerThread(tg);//初始化终结线程  

177.         finalizer.setPriority(Thread.MAX_PRIORITY - 2);  

178.         finalizer.setDaemon(true);  

179.         finalizer.start();  

180.     }  

181.   

182. }  

好吧,看完代码之后还是要提醒一下,一般不用终结器。


以上是关于jdk源码解析--Finalizer类的主要内容,如果未能解决你的问题,请参考以下文章

jdk源码解析--AbstractStringBuilder类

jdk源码解析--String 类

jdk源码解析--BitSet类

jdk源码解析--Writer类

jdk源码解析--WeakReference/softReference类

jdk源码解析--ThreadPoolExecutor类