Java Drools 6.5.0.Final中的StatefulKnowledgeSession内存泄漏

Java Drools 6.5.0.Final中的StatefulKnowledgeSession内存泄漏,java,memory-leaks,drools,Java,Memory Leaks,Drools,我一直在尝试查找我的应用程序中的内存泄漏问题,该应用程序使用Drools 6.5.0.Final作为其核心组件之一 我不确定这是否真的是一个流口水的问题。为了支持我的假设,我编写了以下规则并将其部署到Drools中 package test import memleak.MemoryLeak; import event.SetupEvent; rule "Memory Leak" no-loop true when $event: SetupEvent();

我一直在尝试查找我的应用程序中的内存泄漏问题,该应用程序使用Drools 6.5.0.Final作为其核心组件之一

我不确定这是否真的是一个流口水的问题。为了支持我的假设,我编写了以下规则并将其部署到Drools中

package test
import memleak.MemoryLeak;
import event.SetupEvent;

rule "Memory Leak"
    no-loop true
    when
        $event: SetupEvent();
    then
       new MemoryLeak().leak();
end
在leak()方法中,它只创建一个200MB字节数组

package memleak;

import java.util.ArrayList;
import java.util.List;

public class MemoryLeak {

    private static final int _10MB = 10 * 1024 * 1024;

    public List<MemObject> leak() {
        int loop = 20;
        List<MemObject> byteArr = new ArrayList<MemObject>(loop);
        for (int i = 0; i < loop; ++i) {
            byteArr.add(new MemObject(_10MB));
        }

        return byteArr;
    }
}

class MemObject {

    private byte[] contents;

    public MemObject(int size) {
        contents = new byte[size];
    }
}
packagememleak;
导入java.util.ArrayList;
导入java.util.List;
公共类记忆库{
专用静态最终整数_10MB=10*1024*1024;
公开名单泄漏(){
int循环=20;
List byteArr=新数组列表(循环);
for(int i=0;i
在使用SetupEvent触发规则后,我调用了会话的“dispose”方法。但我发现我之前分配的内存没有被释放

此外,我还尝试使用规则中的“insert”方法将字节数组插入会话。它似乎也没有被释放

有人知道这件事吗

提前谢谢


史蒂文

在您的情况下,最有可能的内存将在之后被释放。
您可以通过以下方式释放有状态会话的内存:


使用域对象和规则,下面是插入10K
SetupEvent
s的测试

@DroolsSession(resources = "classpath:/test.drl", log = false)
public class PlaygroundTest {

    @Rule
    public DroolsAssert drools = new DroolsAssert();

    @Test
    public void testIt() {
        for (int i = 0; i < 10_000; i++)
            drools.insertAndFire(new SetupEvent());
    }
}
@DroolsSession(resources=“classpath:/test.drl”,log=false)
公开课操场测试{
@统治
public DroolsAssert drools=新DroolsAssert();
@试验
公开无效测试(){
对于(int i=0;i<10_000;i++)
drools.insertAndFire(新的SetupEvent());
}
}
我甚至没有收回
SetupEvent
s,它们没有字段,大小非常小。测试运行约5.5分钟。告诉我内存泄漏

200M内存分配不是无cpu操作,在我的机器上平均需要32ms。测试正在进行内存分配和垃圾收集


您能否创建一个复制问题的测试?

有状态会话?是的。有状态的会议。有什么想法吗?嗨。谢谢你的回答。
delete
方法确实删除了我不再需要的事实。但这意味着我必须手动删除所有事实。我想要的是释放我将不再使用的某个会话所使用的所有内存空间。此外,如果我分配内存,但不
将相应的事实插入会话中(正如我上面演示的那样),我就没有机会手动调用
删除
。在这种情况下,
System.gc()
是释放内存的唯一方法吗?Java决定何时清理内存,我认为您的测试有问题。您正在监视内存消耗,但不能期望jvm在对象不再使用时立即清除内存。当我提到gc jvm提示时,这就是我的观点。将对象插入工作内存时,肯定会创建新的强引用。当你们收回对象时,强引用必须消失,或者你们在口水中发现了错误。若您不想删除对象,但想处理所有会话,也可以。但您的期望是错误的,dispose必须清理所有强引用。虽然这可能是真的,但在清理会话对象时,很可能会清理强引用。所以你的测试很可能是无效的。另一点,当您创建对象但不创建对它的引用时,它立即成为gc的主题。我想知道你为什么需要处理这个会话。您的测试不太可能反映问题。正确的方向是创建一个复制OOE的测试,在这里发布,然后我们可以实施(建议)和“测量”修复。我完全同意你的看法。没有引用的对象受GC约束。但这正是让我困惑的地方。理论上,
newmemoryLeak().leak()分配的内存应该在对象创建后立即清除,因为它没有被任何其他对象引用。但事实上,即使在几个小时后,我仍然可以在堆空间中找到它,并且内存使用率似乎没有下降。如果我能找到更多线索,我会再回来的。谢谢你的回答。