以下JavaCV代码有什么问题?我尝试填充CvSeq以进行进一步的工作,但JVM 几乎在各个地方可靠地与EXCEPTION_ACCESS_VIOLATION崩溃,最常见的是[msvcr100.dll+0x3c19b] memcpy+0x20b
或[opencv_core243.dll+0x61793] cvSeqPush+0x133
public static void main(String[] args) {
CvMemStorage memStorage = CvMemStorage.create();
CvSeq seq = cvCreateSeq(0, Loader.sizeof(CvSeq.class),
Loader.sizeof(CvPoint.class), memStorage);
for (int j=0; j<1000000; j++) {
CvPoint cvPoint = cvPoint(j, j+1);
System.out.println(j);
cvSeqPush(seq, cvPoint);
}
}
在我的配置中,它经常在大约50000次迭代后失败,但有时在其他计数或根本没有。显然存在一些分配/解除分配错误。它只在不在调试模式下运行时才会重现。
如果我在20000次迭代后显式调用System.gc()
,它会在GC之后立即在cvSeqPush
内失败(或稍后1-2次迭代,可能是因为来自解除分配空间的指针恰好指向正确的地址)。或者,如果我同时设置了Xmx
和Xms
个参数,它迟早会失败。可能正在使用的东西是自动解除分配的。
答案 0 :(得分:1)
问题是,垃圾收集器在代码中最后一次引用后将memStorage
识别为未使用,而不是在块的末尾。这会导致在循环中发生的第一个GC之后的本机对象释放。这就是为什么只在不使用调试器时才会重现问题。
解决方法是在循环后添加对memStorage
的引用,以防止GC释放它。最好的方法是调用memStorage.release()
主动释放本机内存而无需等待GC并防止在仍然需要时过早释放。
请参阅我与JavaCV和JavaCPP作者Samuel Audet讨论的更多原生分配问题:https://groups.google.com/forum/?fromgroups=#!topic/javacv/ffQSkfXnT0o