[jboss-jira] [JBoss JIRA] Commented: (JBRULES-946) RuleBase serialization fails with StackOverflowError
Alexandre Gattiker (JIRA)
jira-events at lists.jboss.org
Sun Jul 8 09:52:51 EDT 2007
[ http://jira.jboss.com/jira/browse/JBRULES-946?page=comments#action_12368177 ]
Alexandre Gattiker commented on JBRULES-946:
--------------------------------------------
I apologize, my report was somewhat lacking. The class below allows to reproduce the bug. It is easily reproducible, in my project I have a large rulebase and I can reproduce the bug by serializing even non-overlapping chunks of it.
The example here crashes with 2000 rules (JDK 1.5.0_08 on Linux) and will even crash with only 1000 rules on JDK 1.6.
Also, if the number of rules is increased to 3000, the serialization crashes with a single-line error message "java.lang.OutOfMemoryError: Java heap space".
The introduction of JBoss Rules in our project has yielded an amazing speed increase, and being able to persist our rule base would be the icing on the cake! Thank you very much for your work.
package com.sample;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.io.StringReader;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.WorkingMemory;
import org.drools.compiler.PackageBuilder;
import org.drools.rule.Package;
/**
* This is a sample file to launch a rule package from a rule source file.
*/
public class DroolsTest {
public static final void main(String[] args) {
try {
RuleBase ruleBase = readRule();
} catch (Throwable t) {
t.printStackTrace();
}
}
/**
* Please note that this is the "low level" rule assembly API.
*/
private static RuleBase readRule() throws Exception {
System.err.println("Reading rules");
Reader source = new StringReader(getRule());
System.err.println("Package");
PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl(source);
Package pkg = builder.getPackage();
System.err.println("Rulebase");
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage(pkg);
// serialize RuleBase
System.err.println("Serialize");
File outFile = new File("out.tmp");
FileOutputStream fout = new FileOutputStream(outFile);
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(ruleBase);
oos.close();
return ruleBase;
}
static String getRule() {
StringBuffer buf = new StringBuffer(80000);
buf.append("package mypackage\n");
buf.append("import com.sample.DroolsTest.Parent\n");
buf.append("import com.sample.DroolsTest.Child\n");
buf.append("import com.sample.DroolsTest.Item\n");
for (int i = 0; i < 1000; i++) {
buf.append("rule 'Rule " + i + "'\n");
buf.append(" when\n");
buf.append(" $g:Parent()\n");
buf
.append(" $c:Child(parent==$g,code=='" + i
+ "')\n");
buf
.append(" Item(parentObject==$c,name=='xxx1', value == '1')\n");
buf
.append(" Item(parentObject==$c,name=='xxx2',value == '1')\n");
buf
.append(" Item(parentObject==$g,name=='xxx3',value == '200')\n");
buf.append(" then\n");
buf.append(" System.out.println('2');\n");
buf.append("end\n");
}
return buf.toString();
}
public static class Parent {
}
public static class Child {
Parent parent;
String code;
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
public static class Item {
Object parentObject;
String name;
String value;
public Object getParentObject() {
return parentObject;
}
public void setParentObject(Object parentObject) {
this.parentObject = parentObject;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
> RuleBase serialization fails with StackOverflowError
> ----------------------------------------------------
>
> Key: JBRULES-946
> URL: http://jira.jboss.com/jira/browse/JBRULES-946
> Project: JBoss Rules
> Issue Type: Bug
> Security Level: Public(Everyone can see)
> Affects Versions: 4.0.0.MR2, 4.0.0.MR3
> Reporter: Alexandre Gattiker
> Assigned To: Mark Proctor
> Fix For: 4.0.0.MR4
>
>
> I created 920 rules, all in this format, with different values in the string literals.
> rule "Rule_1"
> when
> $g:Parent()
> $c:Child(parent==$g,code=="yyy1")
> Item(parentObject==$c,name=="xxx1", value == "1")
> Item(parentObject==$c,name=="xxx2",value == "1")
> Item(parentObject==$g,name=="xxx3",value == "200")
> then
> System.out.println("2");
> end
> With the following code, I create a RuleBase that I serialize.
> RuleBase ruleBase = RuleBaseFactory.newRuleBase();
> PackageBuilderConfiguration conf = new PackageBuilderConfiguration();
> conf.setCompiler(PackageBuilderConfiguration.JANINO);
> Reader source = new InputStreamReader(PolicyServiceImpl.class.getResourceAsStream(fileName));
> PackageBuilder builder = new PackageBuilder(conf);
> builder.addPackageFromDrl(source);
> Package pkg = builder.getPackage();
> ruleBase.addPackage(pkg);
> //serialize RuleBase
> File outFile = new File(f.getPath() + ".tmp");
> FileOutputStream fout = new FileOutputStream(outFile);
> ObjectOutputStream oos = new ObjectOutputStream(fout);
> oos.writeObject(ruleBase);
> oos.close();
> The serialization fails with the following exception. Otherwise the RuleBase is perfectly fine and working.
> java.lang.StackOverflowError
> at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream$BlockDataOutputStream.write(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java(Compiled Code))
> at java.util.ArrayList.writeObject(ArrayList.java(Compiled Code))
> at sun.reflect.GeneratedMethodAccessor16.invoke(Unknown Source)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java(Compiled Code))
> at java.lang.reflect.Method.invoke(Method.java(Compiled Code))
> at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java(Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java(Inlined Compiled Code))
> at java.util.ArrayList.writeObject(ArrayList.java(Compiled Code))
> at sun.reflect.GeneratedMethodAccessor16.invoke(Unknown Source)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java(Compiled Code))
> at java.lang.reflect.Method.invoke(Method.java(Compiled Code))
> at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java(Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java(Inlined Compiled Code))
> at java.util.ArrayList.writeObject(ArrayList.java(Compiled Code))
> at sun.reflect.GeneratedMethodAccessor16.invoke(Unknown Source)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java(Compiled Code))
> at java.lang.reflect.Method.invoke(Method.java(Compiled Code))
> at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java(Compiled Code))
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
> (last four lines repeated over 1000 times)
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the jboss-jira
mailing list