Memory leak in StatelessKnowledgeSessionImpl when fireAllRules() throws an Exception during a rule execution

Solution Unverified - Updated

Environment

  • Red Hat JBoss SOA Platform (SOA-P)
    • 5.2.0

Issue

  • A Drools Rule fails in the action pipe line with a ConsequenceException (while using businessruleprocessor) that is propagated back to the jms layer as an exception on JmsServerSession.
  • After a certain number of errors the servers is busy with Garbage Collection
  • A large portion of the heap is dedicated to references held by DroolsRuleBaseState.

Resolution

  • This a known issue 1 and it incorporates this fix provided in Drools Community 2 . As of now to resolve this issue, upgrade to SOA-P 5.3.1 and apply Roll-up patch #5 3 .

  • If the upgrade and the Roll-up patch (mentioned above) is not a feasible solution, then the Drools consequence exception handler concept can be used to dispose the session after a runtime exception.

Steps for this approach:

  1. Create an implementation of the ConsequenceExceptionHandler interface:
/*
To the extent possible under law, Red Hat, Inc. has dedicated all copyright to this software to the public domain worldwide, pursuant to the CC0 Public Domain Dedication. This software is distributed without any warranty.  See <http://creativecommons.org/publicdomain/zero/1.0/>.
*/


package drools.sample;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.Activation;
import org.drools.runtime.rule.ConsequenceException;
import org.drools.runtime.rule.ConsequenceExceptionHandler;
import org.drools.runtime.rule.WorkingMemory;


public class DisposeMemoryConsequenceExceptionHandler implements ConsequenceExceptionHandler, Externalizable {

    public DisposeMemoryConsequenceExceptionHandler() {
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
    }

    public void handleException(Activation activation, WorkingMemory workingMemory, Exception e) {
        if (workingMemory instanceof StatefulKnowledgeSession) {
            ((StatefulKnowledgeSession) workingMemory).dispose();
        }

        throw new ConsequenceException(e, activation.getRule());
    }
}
  1. Start server with custom error handler property:
./run.sh -Ddrools.consequenceExceptionHandler=drools.sample.DisposeMemoryConsequenceExceptionHandler

Root Cause

  • The org.jboss.internal.soa.esb.services.rules.DroolsRuleBaseState retention is because statelessknowledgeSession does not call the dispose() method when there is an exception. Thus, the underlying resources do not get freed after the exception has been handled.

  • This bug has been fixed in the upstream Drools project 4.

  • For BRMS, Roll-up patch #3 for 5.3.1 includes this fix and is available from the customer support portal 5.

  • For SOA-P, Roll-up patch #5 6 can be applied on SOA-P 5.3.1 release to fix this issue. But, do note that to apply this patch first upgrade to SOA-P 5.3.1 , as the Roll-up patch #5 6 is only intended to be applied on SOA-P 5.3.1 only.

Diagnostic Steps

Components
Category
Tags

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.