我正在尝试使用Java 7中的ObjectOutputStream将第三方可外部化的类实例(Drools KnowledgePackage)的集合(ArrayList)写入文件。如果我限制KnowledgePackage的大小,使结果文件小于等于1GB,那一切都很好。如果我让实例进一步扩展一小部分,以至于(我相信)文件将大于1GB,那么我将收到以下故障。
代码如下:
Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream(packageFileName) );
out.writeObject( kpkgs );
out.close();
错误看起来像这样:
Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at java.util.Arrays.copyOf(Arrays.java:2271)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1876)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1785)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1188)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
at org.drools.rule.Package.writeExternal(Package.java:164)
at org.drools.definitions.impl.KnowledgePackageImp.writeExternal(KnowledgePackageImp.java:161)
at java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1458)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
at java.util.ArrayList.writeObject(ArrayList.java:742)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
... <my code>
增加堆大小没有任何区别。如果继续进行下去,似乎还有其他事情。
我相信原因是ObjectOutputStream的内部字节数组管理。根据https://bugs.openjdk.java.net/browse/JDK-6991552和https://bugs.openjdk.java.net/browse/JDK-6464834的定义,数组大小每增加一个现有数组就会增加一倍+ 1筋疲力尽。这意味着当数组达到> = 1GB时,如果不破坏Java的(2 ^ 31)-1最大数组大小,它将无法进一步增长。
是否有解决方法或替代方法来编写这些对象,所以我至少可以输出2GB,理想情况下是不确定的大小。也许存在替代方法来写入和读取如此大的对象?
尝试使用HotSpot 1.7.0_51和OpenJDK 1.7.0_45获得相同的结果。如果相关,Drools版本为5.5.0Final
非常感谢
问题不是jdk,而是Drools。如果查看堆栈跟踪,则问题在于该对象正在被序列化为ByteArrayOutputStream。jdk并没有这样做,这就是org.drools.rule.Package.writeExternal
方法的实现方式:http : //grepcode.com/file/repo1.maven.org/maven2/org.drools/drools-core/5.4.0.Final/org/ drools / rule / Package.java#Package.writeExternal%28java.io.ObjectOutput%29。
您应该向流口水提交错误(关于序列化较大的规则包)。
或者,看起来好像您使用的是DroolsObjectOutputStream,然后它跳过辅助的内存中序列化并直接使用给定的流。这可能会解决您的问题(假设您可以将DOOS用于您的用例)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句