欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

那么只有可能 昆山软件定制开发 是finalize方法慢了

点击: 次  来源:宝鼎软件 时间:2017-07-10

原文出处: scugxl的专栏

配景

某天发明客户情况一直有OOM产生,并且是路线状的内存增长. 较量郁闷.

 那么只有大概 昆山软件定制开拓 是finalize要领慢了

Abstract

这个文章内里会描写以下几件工作:

1. 在Java中有OOM应该怎么阐明?
2. Java finalizer为什么会激发OOM?
3. 为什么不能利用Thread.stop

Java中产生OOM应该怎么阐明

大大都时候Java都做得足够好. 可是没步伐照旧有大概会有OutOfMemoryError(OOM) 产生. 那么我们应该怎么阐明一个OOM错误呢?

拿到内存转储

方法1:自动转储

当OOM产生时, Java可以自动实验(best effort)生成一个堆转储.只需要你在启动参数中加上如下参数:

-XX:+HeapDumpOnOutOfMemoryError

这种方法生成的文件会在java的事情目次内里, 名字叫 java_pidXXX.hprof

方法2:手动转储

有时候你已经可以发明某个Java历程占用了许多内存了. 是时候手动导出一个堆内存了.
利用jmap. jmap是一个jdk自带的东西, 在jdk/bin下面,

jmap -dump:format=b,file=heap.bin <pid>   
jmap -F -dump:format=b,file=heap.bin <pid>  强制导出

有一点很重要: 出于兼容性思量,必然利用和你运行JRE**运行版内情同**的jmap东西.

运用东西阐明

常见的内存阐明东西是Eclipse的Memory analyzer 和 Jvisualvm.

Eclispe memory analyzer/ MAT

这个是Eclipse推出的一个可视化内存阐明东西.

 那么只有大概 昆山软件定制开拓 是finalize要领慢了

内里的许多组件都很好用:

1. histogram 列出每个class有几多instance
2. Leak suspects 列出了东西以为大概有内存泄漏的处所.

好比Leak suspects页面的下图:

 那么只有大概 昆山软件定制开拓 是finalize要领慢了

从上图可以看出, Finalizer线程占用860M的内存, 约93%的空间.

假如这些尺度的页面不能让你获得你存眷的对象, 可以回收OQL console. 就是上图左上角第4个图标.
回收OQL 我们可以做许多的工作, 好比列出Finalizer工具引用的哪些工具都是啥:
列出所有URLConnection的url:

SELECT f.referent.url.toString() FROM java.lang.ref.Finalizer f WHERE f.referent.toString().startsWith("sun.net.www.protocol.https.HttpsURLConnectionImpl")

 那么只有大概 昆山软件定制开拓 是finalize要领慢了

mat的oql参考地点:http://help.eclipse.org/neon/index.jsp?topic=/org.eclipse.mat.ui.help/welcome.html

更强大的Jvisualvm

jdk自带的jvisualvm也可以阐明堆转储.

 那么只有大概 昆山软件定制开拓 是finalize要领慢了

它提供了比MAT越发强大的阐明成果.

MAT是无法做到雷同于sql groupby filter, top 之类的操纵的. 可能越发巨大的查询. 可是在jvisualvm我们可以实现很巨大的查询:

好比下面的query可以实现: 我想查察Finalizer所引用的工具中, 前10个instance最多的class都是啥:

var counts = {};
var alreadyReturned = {};
top(
    filter(
        sort(
            map(heap.objects("java.lang.ref.Finalizer"),
                function (fobject) {
                    var className = classof(fobject.referent)
                    if (!counts[className]) {
                        counts[className] = 1;
                    } else {
                        counts[className] = counts[className] + 1;
                    }
                    return {string: className, count: counts[className]};
                }),
            'rhs.count-lhs.count'),
        function (countObject) {
            if (!alreadyReturned[countObject.string]) {
                alreadyReturned[countObject.string] = true;
                return true;
            } else {
                return false;
            }
        }),
        "rhs.count > lhs.count", 10);

大抵表明下:

heap.objects(“java.lang.ref.Finalizer”)指定了堆上这个类的所有instance;
在map中, 每个record被映射为具有2个属性的工具:{string:className, count[className]}, 属性string, 代表class名字, 属性count代表它的instance个数;
在排序函数中rhs代表右边的元素, lhs代表左边的元素.
示例输出(不是前面的heap,可是不影响抚玩)

 那么只有大概 昆山软件定制开拓 是finalize要领慢了

jvisualvm的oql参考地点:https://visualvm.github.io/documentation.html (在内里的OQL部门)

Java Finalizer为啥会激发OOM

从前面的heap已经看到了, 有许多的instance都被Java中的Finalizer线程引用了.

什么是Finalizer