您的 Java 版本的 SimpleClass 应该做两件事。一,保留一个私有的 long 值,该值将 C++ 指针的值存储到后备本机对象(您可能必须使用 BigInteger,具体取决于本机指针的大小 - unsigned long long?)。第二,使公共方法(例如setIntVal
)本地化。
public class SimpleClass {
private long nativePtr;
public SimpleClass() {
nativePtr = initNativeSimpleClass();
}
public void destroy() {
destroyNativeSimpleClass();
nativePtr = 0L;
}
protected void finalize() throws Throwable {
destroyNativeSimpleClass();
nativePtr = 0L;
}
public native int getIntVal();
public native void setIntVal(int val);
private native long initNativeSimpleClass();
private native void destroyNativeSimpleClass();
}
然后在您的 JNI 代码中实现这些本地方法。该initNativeSimpleClass()
方法将新建一个支持 C++ 的SimpleClass
. 然后该destroyNativeSimpleClass()
方法将删除该实例。访问器方法将使用 的值nativePtr
,将其转换为真正的指针,并在本机支持实例上执行适当的操作。
这个习惯用法带来了内存泄漏的真正风险,因为该类的用户在使用完实例后必须调用destroy。如果他们不这样做,则支持的本机实例可能不会被正确销毁。正如我在示例中所示,您可以覆盖finalize
以调用本机销毁器函数,但所有关于如何不能依赖 finalize 的警告仍然适用。通过nativePtr
在销毁时将值设置为 0,您可以避免在多次调用销毁时出现段错误(在 C++ 中删除 NULL 是安全的)。