Mar*_*ier 9 c++ java java-native-interface
我以前会问这个问题,但我在这里找不到......
我已经使用SWIG在C++类周围创建了一个JNI包装器.一切都很好,除了Java似乎永远不会调用类的finalize(),因此反过来,我的类的析构函数永远不会被调用.类的析构函数执行一些最终文件I/O,所以不幸的是,这不仅仅是一个小的内存泄漏.
通过Google搜索,似乎没有办法强制Java到GC并销毁对象.真正?
我知道我可以操作我的SWIG文件并创建一个可以调用C++析构函数的java函数,但是这个类被最终用户用在几种不同的平台/语言中,所以添加一个Java只会造成我们的技术不一致作家们不会喜欢.
您无法使用System.gc()强制GC.此外,如果您的应用程序仅运行一小段时间,然后您的终结器根本不运行(JVM在退出时不运行它),则无法保证会运行GC.你应该为你的类创建一个close()或destroy()或者任何函数,当你完成使用这个类的实例时,最好从finally块中调用它.
MyClass x = null;
try{
x = new MyClass();
x.work();
} finally {
if (x!=null)
x.close();
}
Run Code Online (Sandbox Code Playgroud)
在我看来,Java终结器几乎没用,当然也不能替代C++析构函数.不幸的是,Java没有替代C++ RAII.
不要试图强制Java完成.当你通过任何事情,所有的功能将处理它.这就是你所能做的一切.
如果您依赖finalize方法中的代码在特定时间运行,则需要重新考虑您的方法.这里的问题是你不知道finalizeJVM 什么时候会被调用,因为你不知道什么时候会被垃圾回收.
您应该考虑的一件事是,因为您的类将在其他项目中重用,所以最终用户可能会以这样的方式使用类的实例,使得它不会被收集或者垃圾收集将会不太可能,例如创建对类实例的静态引用.我认为创建一个close或destroy方法是最安全的选择,以确保与Java对象关联的C++类实例所使用的资源得到适当的释放.
由于重用是一个问题,你可以让C++析构函数检查资源是否已经释放,如果没有,则调用相同的代码,如下所示:
class MyThing {
public:
void close();
~MyThing();
private:
bool released = false;
};
void
MyThing::close() {
// close logic here
this->released = true;
}
MyThing::~MyThing() {
if (!released) {
this->close();
}
}
Run Code Online (Sandbox Code Playgroud)
这样,您现有的C++代码有望不会发生太大变化,并且您可以确保在通过JNI运行的本机代码的上下文中以确定的方式发布资源.