首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >漏的java库慢慢地占用了所有内存,没有抛出OutOfMemoryException,解决办法?

漏的java库慢慢地占用了所有内存,没有抛出OutOfMemoryException,解决办法?
EN

Stack Overflow用户
提问于 2013-05-29 07:07:31
回答 3查看 1.1K关注 0票数 3

我正在使用java odftoolkit库(simple-odf-0.6.6)进行odf文档操作。我们在循环中迭代所有文档:

代码语言:javascript
复制
TextDocument textdoc = TextDocument.loadDocument(odtFileName);
.
changing content of document
.
textdoc.save(anotherOdtFileName);
textdoc.close();
//then all resources/streams are correctly closed, checked that many times by my colleagues :)

当我们迭代数千个文档时,java应用程序慢慢地占用了所有内存,然后随着GC试图释放一些内存,一切都变慢了。我们没有得到OutOfMemoryException。

我试着调优JVM内存大小和GC选项(http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html) --应用程序再花几分钟时间,但是所有的内存又被消耗掉了。

这是应用程序到达所有可用内存时从转储中获取的示例:

代码语言:javascript
复制
652.147: [Full GC 652.147: [Tenured: 454655K->454655K(454656K), 2.2387530 secs] 659263K->659216K(659264K), [Perm : 41836K->41836K(42112K)], 2.2388570 secs] [Times: user=2.25 sys=0.00, real=2.23 secs] 
654.387: [Full GC 654.387: [Tenured: 454656K->454656K(454656K), 2.2661510 secs] 659263K->659223K(659264K), [Perm : 41836K->41836K(42112K)], 2.2663190 secs] [Times: user=2.26 sys=0.00, real=2.26 secs] 
656.654: [Full GC 656.654: [Tenured: 454656K->454656K(454656K), 2.4117680 secs] 659263K->659229K(659264K), [Perm : 41836K->41836K(42112K)], 2.4118970 secs] [Times: user=2.41 sys=0.00, real=2.41 secs]

如您所见,只有很少的kB已经发布,GC非常慢(超过2秒)。

这个jmap直方图显示了最大的消费者:

代码语言:javascript
复制
 num     #instances         #bytes  class name
----------------------------------------------
   1:       2535190       99077856  [C
   2:       2529791       60714984  java.lang.String
   3:         21085       27956544  [B
   4:        389820       16181680  [Ljava.lang.Object;
   5:        147111       13373896  [Ljava.util.HashMap$Entry;
   6:        108426       13180496  <constMethodKlass>
   7:        518834       12452016  java.util.HashMap$Entry
   8:        108426        9547136  <methodKlass>
   9:        321713        7721112  java.util.Vector
  10:        306308        7351392  org.apache.xerces.dom.AttributeMap
  11:        144353        6928944  java.util.HashMap
  12:         10230        5879960  <constantPoolKlass>
  13:         10230        5089344  <instanceKlassKlass>
  14:        114065        4562600  org.odftoolkit.odfdom.dom.attribute.text.TextStyleNameAttribute
  15:         58248        4193856  org.odftoolkit.odfdom.incubator.doc.text.OdfTextParagraph
  16:         90041        3601640  org.odftoolkit.odfdom.pkg.OdfAlienAttribute
  17:         36437        3459000  [I
  18:         48609        3110976  java.util.zip.ZipEntry
  19:          7454        2939616  <constantPoolCacheKlass>
  20:         36491        2627352  org.odftoolkit.odfdom.incubator.doc.style.OdfStyle
  21:         36399        2620728  org.odftoolkit.odfdom.incubator.doc.text.OdfTextSpan
  22:         58397        2335880  org.odftoolkit.odfdom.dom.attribute.style.StyleNameAttribute
  23:         65517        2096544  org.apache.xerces.dom.TextImpl
  24:         24270        1747440  org.odftoolkit.odfdom.incubator.doc.text.OdfTextListLevelStyleBullet
  25:         36511        1460440  org.odftoolkit.odfdom.dom.attribute.style.StyleFamilyAttribute
  26:         24335        1362760  org.odftoolkit.odfdom.dom.element.style.StyleParagraphPropertiesElement
  27:         24320        1361920  org.odftoolkit.odfdom.dom.element.style.StyleListLevelPropertiesElement
  28:         24320        1361920  org.odftoolkit.odfdom.dom.element.style.StyleListLevelLabelAlignmentElement
  29:         10933        1316952  java.lang.Class
  30:         29175        1167000  org.odftoolkit.odfdom.dom.attribute.style.StyleParentStyleNameAttribute
  31:         19464        1089984  org.odftoolkit.odfdom.dom.element.style.StyleFontFaceElement
  32:         68003        1088048  java.lang.Integer
  33:          3531        1082640  <methodDataKlass>
  34:         26757        1070280  org.odftoolkit.odfdom.dom.attribute.fo.FoMarginLeftAttribute
  35:         26752        1070080  org.odftoolkit.odfdom.dom.attribute.fo.FoTextIndentAttribute
  36:         24330         973200  org.odftoolkit.odfdom.dom.attribute.style.StyleWritingModeAttribute
  32:         68003        1088048  java.lang.Integer
  33:          3531        1082640  <methodDataKlass>
  34:         26757        1070280  org.odftoolkit.odfdom.dom.attribute.fo.FoMarginLeftAttribute
  35:         26752        1070080  org.odftoolkit.odfdom.dom.attribute.fo.FoTextIndentAttribute
  36:         24330         973200  org.odftoolkit.odfdom.dom.attribute.style.StyleWritingModeAttribute
  37:         24320         972800  org.odftoolkit.odfdom.dom.attribute.text.TextListLevelPositionAndSpaceModeAttribute
  38:         24320         972800  org.odftoolkit.odfdom.dom.attribute.text.TextLevelAttribute
  39:         24320         972800  org.odftoolkit.odfdom.dom.attribute.text.TextListTabStopPositionAttribute
  40:         24320         972800  org.odftoolkit.odfdom.dom.attribute.text.TextLabelFollowedByAttribute
  41:         24315         972600  org.odftoolkit.odfdom.dom.attribute.fo.FoLineHeightAttribute
  42:         24270         970800  org.odftoolkit.odfdom.dom.attribute.text.TextBulletCharAttribute
  43:         17064         955584  org.odftoolkit.odfdom.dom.element.style.StyleTextPropertiesElement
  44:         38372         920928  java.util.ArrayList
  45:         12135         873720  org.odftoolkit.odfdom.dom.element.text.TextAElement

如您所见,内存中有很多与of相关的类。

有什么有效的方法来解决这个问题吗?如果能够在运行时从我们的应用程序中卸载odftoolkit并再次加载它以摆脱内存中的所有对象(很明显,它是链接在一起的,GC不能做任何有用的事情),那就太好了。

我们还考虑为较小的文档组单独运行关键代码,但这并不能解决问题的原因。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-29 07:21:18

您很可能有存储泄漏,或者是由于库本身的一些问题,或者是因为您没有适当地使用它。我们需要一个正确构造的minimal reproducible example来知道哪一个。

您所看到的糟糕性能是典型的"GC死亡螺旋“行为,应用程序花费越来越多的时间运行GC并回收越来越少的内存。它很可能最终会导致一个OOME,在几分钟或几个小时的GC颠簸。

处理死亡螺旋的方法是限制使用UseGCOverheadLimit交换机进行垃圾收集所花费的时间。如果GC占用指定的时间比例,JVM会主动抛出一个OOME,其消息是"GC开销限制超过了“。这是件好事。一般来说。

然后你试着追踪储藏室的泄漏。

许多资源都涵盖了跟踪Java存储泄漏。首先,这里是关于这个主题的StackOverflow问答:

其基本思想是使用一个工具(其中有许多)来识别泄漏的对象,并在对象引用链中进行工作,以找出当不应该访问对象时为什么是可访问的。

票数 4
EN

Stack Overflow用户

发布于 2013-05-29 09:37:39

您可以编写一些测试来验证以下几点:

  1. 库本身是否在最简单的情况下泄漏?例如使用代码,如: 公共无效loadSaveDocument(String fileInName,String fileOutName)抛出异常{ OutputStream fileOutStream =新FileOutputStream(fileOutName);TextDocument textdoc = TextDocument.loadDocument(fileInName);textdoc.addParagraph(“添加文本”);textdoc.save(fileOutStream);textdoc.close()};
  2. 如果是的话,一个务实的解决方案将是找到一个解决方案--如前面所建议的那样,使用单独的程序。
  3. 如果没有,是否有特定的文件导致泄漏?尝试通过上面的代码运行所有文档。
  4. 或者,如果没有导致泄漏的特定文档,那么您所使用的文档的特定修改可能会导致泄漏?
  5. 如果不是,请检查与应用程序代码相比,简单代码有什么不同。

我还建议使用像JProfiler这样的分析器,并拍摄一些快照。有关如何使用它的答案,请参见How to find memory leak in java using JProfiler?

票数 2
EN

Stack Overflow用户

发布于 2013-05-29 08:49:09

您可以查看odf库,以找出您正在使用的版本的任何预退出问题。

另外,一种解决方法是通过System.exec调用将所有文档处理转换为另一个vm。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16807576

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档