[jboss-jira] [JBoss JIRA] Commented: (JBRULES-740) IncompatibleClassChangeError working with ShadowProxy

Edson Tirelli (JIRA) jira-events at lists.jboss.org
Thu Mar 22 08:03:53 EDT 2007


    [ http://jira.jboss.com/jira/browse/JBRULES-740?page=comments#action_12356978 ] 
            
Edson Tirelli commented on JBRULES-740:
---------------------------------------

Dirk, it took me some time to realize something, but I think I may know what is happening. Unfortunatelly, it is not something "easy" to solve.

First, let me explain what a ShadowFact is:

It is a copy of every fact you assert into working memory, in a way we can control the changes done to the fact state and only apply it at safe points. An analogy that can be made is with transactions: when inside a transaction (database for instance) you can modify all the data, but it only becomes visible to the world after a commit.

We implement Shadow Facts through a proxy.

Problem is: how to calculate hashcodes and determine equality between 2 facts if we don't know (like in databases) what is the primary key? We can't delegate the calls to the real instance, because it would be calculating hashcode/equals over not commited values. So, we need to intercept and calculate that ourselves. 
Right now, what hashcode does is calculate the value based on all attributes values and equals compare attribute by attribute until either it finds one that is different or all are equal.

This strategy usually works well, except that the class you sent me as an example has a ton of fields. I think what is happening is that it is taking it a long time to calculate hashes and equals during the fact propagation.

Hashcode is simple to cache and will propably improve performance considerably, even using full attributes calculation, but equals() is an incognite to me... I don't have an answer right now on how to deal with equals, besides finding a way to "inspect" the bytecode of the original class to infer what is being done in there and doing a similar thing in the proxy class... I will take a look in that and see if I can do something like that using ASM.



> IncompatibleClassChangeError working with ShadowProxy
> -----------------------------------------------------
>
>                 Key: JBRULES-740
>                 URL: http://jira.jboss.com/jira/browse/JBRULES-740
>             Project: JBoss Rules
>          Issue Type: Bug
>      Security Level: Public(Everyone can see) 
>    Affects Versions: 3.1-m2
>         Environment: Trunk (revision 10170)
>            Reporter: Dirk Bergstrom
>         Assigned To: Edson Tirelli
>             Fix For: 3.1-m2
>
>         Attachments: Record.java, RLIRecord.java, stacktraces.txt
>
>
> I'm getting an exception while asserting objects into the working memory.  Depending on the timing, I get different stacktraces leading up the same exception on the same generated class.  I have 15 rules and three types of objects in the working memory.  2500 User objects, 37 Milestone objects, and 2000 RLI objects.  If I assert all the Users and Milestones first, I get the first exception below during assertion of the RLI objects, at the 257th object asserted.  If I arrange to skip that particular record, I can assert a few more before another record trips the bug.  If I put a try/catch block around the assertion and continue after hitting an exception, I can assert about 1600 of the records successfully, and the others reliably throw (ie. if I try to assert them later).  If I assert RLIs first, I get the second stacktrace during assertion of Milestones.  Looks like the problem happens during execution of one or more rules.  I'll attach the RLI class, and its parent class (which is also the parent of the other two classes).
> Exception in thread "RLIs Processor" java.lang.IncompatibleClassChangeError
> 	at net.juniper.dash.data.RLIRecordShadowProxy.hashCode(Unknown Source)
> 	at java.util.HashMap.put(HashMap.java:418)
> 	at java.util.HashSet.add(HashSet.java:194)
> 	at org.drools.reteoo.CollectNode.assertTuple(CollectNode.java:135)
> 	at org.drools.reteoo.CollectNode.assertObject(CollectNode.java:212)
> 	at
> org.drools.reteoo.SingleObjectSinkAdapter.propagateAssertObject(SingleObjectSinkAdapter.java:20)
> 	at org.drools.reteoo.AlphaNode.assertObject(AlphaNode.java:145)
> 	at
> org.drools.reteoo.CompositeObjectSinkAdapter.propagateAssertObject(CompositeObjectSinkAdapter.java:304)
> 	at org.drools.reteoo.ObjectTypeNode.assertObject(ObjectTypeNode.java:176)
> 	at org.drools.reteoo.Rete.assertObject(Rete.java:121)
> 	at org.drools.reteoo.ReteooRuleBase.assertObject(ReteooRuleBase.java:196)
> 	at
> org.drools.reteoo.ReteooWorkingMemory.doAssertObject(ReteooWorkingMemory.java:68)
> 	at
> org.drools.common.AbstractWorkingMemory.assertObject(AbstractWorkingMemory.java:729)
> 	at
> org.drools.common.AbstractWorkingMemory.assertObject(AbstractWorkingMemory.java:548)
> Exception in thread "Milestones and NPI Processor" java.lang.IncompatibleClassChangeError
> 	at net.juniper.dash.data.RLIRecordShadowProxy.hashCode(Unknown Source)
> 	at java.util.HashMap.put(HashMap.java:418)
> 	at java.util.HashSet.add(HashSet.java:194)
> 	at org.drools.reteoo.CollectNode.assertTuple(CollectNode.java:135)
> 	at org.drools.reteoo.CompositeTupleSinkAdapter.propagateAssertTuple(CompositeTupleSinkAdapter.java:30)
> 	at org.drools.reteoo.JoinNode.assertTuple(JoinNode.java:116)
> 	at org.drools.reteoo.SingleTupleSinkAdapter.createAndPropagateAssertTuple(SingleTupleSinkAdapter.java:55)
> 	at org.drools.reteoo.LeftInputAdapterNode.assertObject(LeftInputAdapterNode.java:147)
> 	at org.drools.reteoo.SingleObjectSinkAdapter.propagateAssertObject(SingleObjectSinkAdapter.java:20)
> 	at org.drools.reteoo.AlphaNode.assertObject(AlphaNode.java:145)
> 	at org.drools.reteoo.SingleObjectSinkAdapter.propagateAssertObject(SingleObjectSinkAdapter.java:20)
> 	at org.drools.reteoo.ObjectTypeNode.assertObject(ObjectTypeNode.java:176)
> 	at org.drools.reteoo.Rete.assertObject(Rete.java:121)
> 	at org.drools.reteoo.ReteooRuleBase.assertObject(ReteooRuleBase.java:196)
> 	at org.drools.reteoo.ReteooWorkingMemory.doAssertObject(ReteooWorkingMemory.java:68)
> 	at org.drools.common.AbstractWorkingMemory.assertObject(AbstractWorkingMemory.java:729)
> 	at org.drools.common.AbstractWorkingMemory.assertObject(AbstractWorkingMemory.java:548)
> 	at net.juniper.dash.data.DataSource.reconcileAssertedRecords(DataSource.java:190)
> 	at net.juniper.dash.data.DataSource.populateRecords(DataSource.java:150)
> 	at net.juniper.dash.Updater$DataSourceProcessor.work(Updater.java:181)
> 	at net.juniper.dash.Refresher.run(Refresher.java:70)

-- 
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