本地c++库-谁必须释放内存以及如何释放

Native C++ library - who have to release the memory and how?

本文关键字:释放 何释放 内存 本地 c++      更新时间:2023-10-16

这是关于Android的。这句话的语境是:

c++库和java包装器类以及用于处理库中的c++类的本机函数(JNI)。当普通java代码需要c++对象时,它创建相应的java包装器对象,该包装器对象通过本机函数创建c++对象,并在'long'变量中记住指向本机对象的指针。在接下来的所有操作中,包装器将此指针指向本机函数等。

问题:

如何在最后释放所有分配的c++对象?目前每个包装类都有'finalize'方法,它调用本地函数来释放c++对象,但Android不保证调用'finalize'!另一方面,c++库通常不知道java代码分配了多少c++对象和什么类型的对象。

当我们的java应用程序终止时,剩余分配的内存会发生什么?当操作系统卸载本机库时,Android会自动释放从本机库使用的整个堆吗?

在进程生命周期结束时,所有进程内存(Java和c++堆)将被释放并由系统回收。但有一点是,Android活动关闭并不一定会结束这个过程。我不确定那里的进程关闭策略是什么。

另一方面,依赖于垃圾收集和finalize()对我来说听起来像是可靠的设计。你声称——"Android不保证finalize()"。你有什么理由吗?因为如果它附带一个免责声明"当对象作为进程关闭的一部分被释放时…",那么我们仍然是好的。

如果您非常偏执,您可以编写自己的malloc()/free()/realloc()包装器,存储所有已分配对象的列表,并引入一个清除函数来遍历列表并释放所有对象。但是,包含Java对象的对象可能以一种奇怪的僵尸状态结束,在这种状态下,内存已经从它们下面释放出来了。这是一个很棘手的命题,很容易出错。所以我还是要说,要相信垃圾收集者。缺乏这些将是……不安。

由于范例的不同,您必须将显式销毁合并到使用c++资源在底层实现的Java对象中。所以是close()或者其他类似的方法。同样的问题也出现在JNI中,所以这些问题的答案将适用于您:

强制Java调用c++析构函数(JNI)

至于关闭时的内存问题,在我看来,通常最好不要依赖它。如果你达到一个干净的状态,valgrind等可以确保你没有泄漏。

但是从技术的角度来看——因为Android是基于Linux的,我想它会做通常的事情,在进程关闭时释放所有的内存。利用这一点可以使您的程序退出比显式释放内存更快(仅对于使用其他方法来确保维护程序正确性并且在运行时不会泄漏的专家)。

我们正在使用jndi,我们遇到了这样的问题

实际上,问题在于我们重载了finalize()来完成清理。我们通过删除finalize()并创建clean()来解决问题。这个clean()调用执行适当删除操作的JNI函数(并将c++指针设置为空,以防万一)。我们调用clean()就像在c++中调用delete一样(例如,当变量超出作用域时)。

这对我们有用。我希望它对你有用。好运!