是什么导致GMP的这个JNA包装器中的段错误

时间:2012-07-17 19:30:50

标签: java jna gmp

所以,在finalize期间,下面的java代码段错误。

public class Mpz_t extends com.sun.jna.Structure {
    public int _mp_alloc;
    public int _mp_size;
    public NativeLongByReference _mp_d;

    protected void initFieldOrder() {
        setFieldOrder(new String[] { "_mp_alloc", "_mp_size", "_mp_d" });
    }

    public Mpz_t() {
        super();
        initFieldOrder();
        allocateMemory();
        ensureAllocated();
    }

    public static class ByReference extends Mpz_t implements
        Structure.ByReference {

    }

    public static class ByValue extends Mpz_t implements
        Structure.ByValue {

    }

    @Override public void finalize() {
        Gmp.gmp().__gmpz_clear(this);
    }
}
据我所知,

.__gmpz_clear()会破坏C端的结构。如果我撕掉那个部分,就没有段错误,但我的代码会泄漏内存。有人有这方面的想法吗?

我可能会补充一点,它不能可靠地进行段错误。在问题发生之前,它会正确地破坏这些结构中的20个。

2 个答案:

答案 0 :(得分:0)

所以我找到了自己问题的答案,解决方案目前是半熟的。

问题是JNA对__gmpz_clear的调用与垃圾收集器位于不同的线程上,有时垃圾收集器会在__gmpz_clear完成执行之前销毁指针数据和其他内容。通过while(_mp_size > 0) ;添加螺旋锁完全解决了这个问题。

答案 1 :(得分:0)

为了确保清理以正确的顺序运行,您可以考虑覆盖Structure.autoAllocate(int size)以返回自定义Memory对象,该对象会扩充其现有的终结器,以便在现有之前调用__gmpz_clear终结器实际上释放了分配的内存。

public class Mpz_t extends Structure {
    protected Memory autoAllocate(int size) {
        return new Memory(size) {
            protected void finalize() {
                GMP.gmp().__gmpz_clear(this);
                super.finalize();
            }
        };
    }
}

这可以确保在释放内存时总是“清除”。