热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java内存泄漏的故障排除:终结?-Troubleshootingajavamemoryleak:finalization?

Ihaveamisbehavingapplicationthatseemstoleak.Afterabriefprofilerinvestigation,mostmemo

I have a misbehaving application that seems to leak. After a brief profiler investigation, most memory (80%) is held by java.lang.ref.Finalizer instances. I suspect that finalizers fail to run.

我有一个行为不当的应用程序,似乎泄露了。经过简短的分析器调查,大多数内存(80%)由java.lang.ref保存。终结器实例。我怀疑终结器不能运行。

A common cause of this seems to be exceptions thrown from the finalizer. However, the javadoc for the finalize method of the Object class (see here for instance) seems to contradict itself: it states

一个常见的原因似乎是终结器抛出的异常。但是,对象类的finalize方法的javadoc(例如在这里看到)似乎自相矛盾:它声明

If an uncaught exception is thrown by the finalize method, the exception is ignored and finalization of that object terminates.

如果finalize方法抛出未捕获的异常,则会忽略该异常,该对象的终结。

but later, it also states that

但后来,它也指出了这一点

Any exception thrown by the finalize method causes the finalization of this object to be halted, but is otherwise ignored.

finalize方法抛出的任何异常都会导致该对象的终结,但在其他情况下会被忽略。

What should I believe (i.e., is finalization halted or not?), and do you have any tips on how to investigate such apparent leaks?

我应该相信什么?你对如何调查这些明显的泄漏有什么建议吗?

Thanks

谢谢

5 个解决方案

#1


6  

My first step would be to establish whether this is a genuine memory leak or not.

我的第一步是确定这是否是一个真正的内存泄漏。

The points raised in the previous answers all relate to the speed at which objects are collected, not the question of whether your objects are collected at all. Only the latter is a genuine memory leak.

在前面的回答中提出的要点都与收集对象的速度有关,而不是您的对象是否被收集的问题。只有后者才是真正的内存泄漏。

We had a similar predicament on my project, and ran the application in "slow motion" mode to figure out if we had a real leak. We were able to do this by slowing down the stream of input data.

在我的项目中,我们遇到了类似的困境,并以“慢动作”模式运行应用程序,以确定是否出现了真正的泄漏。我们可以通过减慢输入数据流来实现这一点。

If the problem disappears when you run in "slow motion" mode, then the problem is probably one of the ones suggested in the previous answers, i.e. the Finalizer thread can't process the finalizer queue fast enough.

如果在运行“慢动作”模式时,问题消失了,那么问题可能是在前面的答案中提出的问题之一,即终结器线程不能足够快地处理终结器队列。

If that is the problem, it sounds like you might need to do some non-trivial refactoring as described in the page Bringer128 linked to, e.g.

如果这是问题所在,听起来您可能需要做一些重要的重构,如在链接到的页面Bringer128中所描述的。

Now let's look at how to write classes that require postmortem cleanup so that their users do not encounter the problems previously outlined. The best way to do so is to split such classes into two -- one to hold the data that need postmortem cleanup, the other to hold everything else -- and define a finalizer only on the former

现在让我们看看如何编写需要进行死后清理的类,以便他们的用户不会遇到前面提到的问题。最好的方法是将此类类分为两类——一个用于保存需要事后清理的数据,另一个用于保存其他所有内容——并仅在前者上定义终结器

#2


9  

Both quotes say:

这两个报价说:

An exception will cause finalization of this object to be halted/terminated.

一个异常将导致这个对象的终结被停止/终止。

Both quotes also say:

两个报价也说:

The uncaught exception is ignored (i.e. not logged or handled by the VM in any way)

未被捕获的异常被忽略(例如,没有被记录或被VM以任何方式处理)

So that answers the first half of your question. I don't know enough about Finalizers to give you advice on tracking down your memory leak though.

这就回答了你问题的前半部分。我对Finalizers的了解还不够多,我想给你一些关于追踪内存泄漏的建议。

EDIT: I found this page which might be of use. It has advice such as setting fields to null manually in finalizers to allow the GC to reclaim them.

编辑:我找到了这个可能有用的页面。它提供了一些建议,比如在终结器中手动将字段设置为null,以允许GC回收它们。

EDIT2: Some more interesting links and quotes:

更多有趣的链接和引用:

From Anatomy of a Java Finalizer

从Java终结器的剖析

Finalizer threads are not given maximum priorities on systems. If a "Finalizer" thread cannot keep up with the rate at which higher priority threads cause finalizable objects to be queued, the finalizer queue will keep growing and cause the Java heap to fill up. Eventually the Java heap will get exhausted and a java.lang.OutOfMemoryError will be thrown.

终结器线程在系统上没有获得最大优先级。如果“终结器”线程无法跟上高优先级线程导致可终结对象排队的速度,那么终结器队列将继续增长,并导致Java堆填满。最终,Java堆将被耗尽,并使用Java .lang。就会抛出OutOfMemoryError。

and also

it's not guaranteed that any objects that have a finalize() method are garbage collected.

不能保证任何具有finalize()方法的对象都是垃圾收集的。

EDIT3: Upon reading more of the Anatomy link, it appears that throwing exceptions in the Finalizer thread really slows it down, almost as much as calling Thread.yield(). You appear to be right that the Finalizer thread will eventually flag the object as able to be GC'd even if an exception is thrown. However, since the slowdown is significant it is possible that in your case the Finalizer thread is not keeping up with the object-creation-and-falling-out-of-scope rate.

EDIT3:在阅读了更多的解剖学链接之后,似乎在终结器线程中抛出异常会降低它的速度,几乎与调用thread .yield()一样慢。即使抛出异常,终结器线程最终也将标记对象为GC,这似乎是正确的。但是,由于放缓是显著的,所以在您的示例中终结器线程可能没有跟上对象创建和超出范围的速度。

#3


3  

The item 7 of Effective Java second edition is: "Avoid finalizers". I strongly recommend you to read it. Here is an extract that may help you:

有效的Java第二版的第7项是:“避免终结器”。我强烈建议你读一读。这里有一个可以帮助你的摘录:

"Explicit termination methods are typically used in combination with try-finally construct to ensure termination"

“显式终止方法通常与try-finally结构结合使用,以确保终止”

#4


0  

I have same issue with you (below picture). For our case, it because an object has wait(0) in its finalize and it never get notified, which block the java.lang.ref.Finalizer$FinalizerThread. More reference

我和你有同样的问题(下图)。对于我们的例子来说,因为对象在其finalize中等待(0),而它永远不会得到通知,从而阻塞了java.lang.ref.Finalizer$FinalizerThread。更多的参考

  • The Secret Life Of The Finalizer
  • 终结者的秘密生活
  • java/lang/ref/Finalizer.java
  • java / lang / ref / Finalizer.java

objects retained by Finalizer

#5


0  

i have once see a similar problem, that is the finalizer thread can not catch up with the rate of generating finalizable objects.

我曾经遇到过一个类似的问题,那就是终结器线程无法赶上生成可终结对象的速度。

my solution is the make a closed loop control, by use the MemoryMXBean .getObjectPendingFinalizationCount(), a PD( proportinal and diffrential) control algo to control the speed we generate the finalizable objects, since we have a single entry to create it, just sleep number of seconds with the result of pd algo. it works well, though you need to tune the paramter for pd algo.

我的解决方案是使用MemoryMXBean . getobjectpendingfinalizationcount(),一个PD(proportinal和diffrential)控件algo,通过它来控制生成可终结对象的速度,因为我们只有一个条目来创建它,使用PD algo的结果只需要睡眠数秒。它工作得很好,尽管你需要为pd algo调整参数。

hope it helps.

希望它可以帮助。


推荐阅读
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Python语法上的区别及注意事项
    本文介绍了Python2x和Python3x在语法上的区别,包括print语句的变化、除法运算结果的不同、raw_input函数的替代、class写法的变化等。同时还介绍了Python脚本的解释程序的指定方法,以及在不同版本的Python中如何执行脚本。对于想要学习Python的人来说,本文提供了一些注意事项和技巧。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
author-avatar
蓬从蓉Tahirah
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有