Java Drools 6.5.0.Final中的StatefulKnowledgeSession内存泄漏
我一直在尝试查找我的应用程序中的内存泄漏问题,该应用程序使用Drools 6.5.0.Final作为其核心组件之一 我不确定这是否真的是一个流口水的问题。为了支持我的假设,我编写了以下规则并将其部署到Drools中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();
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()分配的内存代码>应该在对象创建后立即清除,因为它没有被任何其他对象引用。但事实上,即使在几个小时后,我仍然可以在堆空间中找到它,并且内存使用率似乎没有下降。如果我能找到更多线索,我会再回来的。谢谢你的回答。