索引
链接
https://mp.weixin.qq.com/s/huwOkXqfuaALnIg6I6J48A
文章截图
简评
最喜欢这种线上问题分析的文章了,长知识!
这次新知道了一个Java内存分析工具:MAT,memory analyzer tool。还有新知道的知识就是“虚引用”,这种工作中没用过的东西都只存在于当初毕业准备面试时的脑子里。今天看了这个文章之后,专门查了一下虚引用,了解到虚引用是需要PhantomReference来使用的。
Phantom意思是幽灵,PhantomReference也就是虚引用,这个类的构造方法需要传入一个引用以及一个ReferenceQueue,当虚引用对象被回收后,虚引用会被放入指定的ReferenceQueue,此时循环查询ReferenceQueue的代码发现队列中有对象了,就知道对象已经被回收了,然后就可以做一些自定义的操作。例如mysql就在发现虚引用连接对象被回收之后做了关闭网络连接的操作,代码简单解释如下:
public void run() { //死循环 for (;;) { try { checkContextClassLoaders(); //此处使用等待5000毫秒获取一个元素的方式进行循环获取 Reference<? extends ConnectionImpl> ref = NonRegisteringDriver.refQueue.remove(5000); if (ref != null) { try { //获取到了虚引用,就调用虚引用的方法做清理操作 ((ConnectionPhantomReference) ref).cleanup(); } finally { NonRegisteringDriver.connectionPhantomRefs.remove(ref); } } } catch (InterruptedException e) { threadRef = null; return; } catch (Exception ex) { // Nowhere to really log this. } } } //下面是ConnectionPhantomReference类定义 static class ConnectionPhantomReference extends PhantomReference<ConnectionImpl> { private NetworkResources io; ConnectionPhantomReference(ConnectionImpl connectionImpl, ReferenceQueue<ConnectionImpl> q) { super(connectionImpl, q); try { this.io = connectionImpl.getIO().getNetworkResources(); } catch (SQLException e) { // if we somehow got here and there's really no i/o, we deal with it later } } //清理方法 void cleanup() { if (this.io != null) { try { this.io.forceClose(); } finally { this.io = null; } } } }
原创文章,作者:geekgao,如若转载,请注明出处:https://www.geekgao.cn/archives/1609