我正在使用java odftoolkit库(simple-odf-0.6.6)进行odf文档操作。我们在循环中迭代所有文档:
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) --应用程序再花几分钟时间,但是所有的内存又被消耗掉了。
这是应用程序到达所有可用内存时从转储中获取的示例:
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直方图显示了最大的消费者:
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不能做任何有用的事情),那就太好了。
我们还考虑为较小的文档组单独运行关键代码,但这并不能解决问题的原因。
发布于 2013-05-29 07:21:18
您很可能有存储泄漏,或者是由于库本身的一些问题,或者是因为您没有适当地使用它。我们需要一个正确构造的minimal reproducible example来知道哪一个。
您所看到的糟糕性能是典型的"GC死亡螺旋“行为,应用程序花费越来越多的时间运行GC并回收越来越少的内存。它很可能最终会导致一个OOME,在几分钟或几个小时的GC颠簸。
处理死亡螺旋的方法是限制使用UseGCOverheadLimit交换机进行垃圾收集所花费的时间。如果GC占用指定的时间比例,JVM会主动抛出一个OOME,其消息是"GC开销限制超过了“。这是件好事。一般来说。
然后你试着追踪储藏室的泄漏。
许多资源都涵盖了跟踪Java存储泄漏。首先,这里是关于这个主题的StackOverflow问答:
其基本思想是使用一个工具(其中有许多)来识别泄漏的对象,并在对象引用链中进行工作,以找出当不应该访问对象时为什么是可访问的。
发布于 2013-05-29 09:37:39
您可以编写一些测试来验证以下几点:
我还建议使用像JProfiler这样的分析器,并拍摄一些快照。有关如何使用它的答案,请参见How to find memory leak in java using JProfiler?。
发布于 2013-05-29 08:49:09
您可以查看odf库,以找出您正在使用的版本的任何预退出问题。
另外,一种解决方法是通过System.exec调用将所有文档处理转换为另一个vm。
https://stackoverflow.com/questions/16807576
复制相似问题