[
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