【每日阅读】2020年05月06日-线上问题分析系列:数据库连接池内存泄漏问题的分析和解决方案

链接

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

发表评论

电子邮件地址不会被公开。 必填项已用*标注

GitLab GitHub
分享本页
返回顶部