当前位置: 首页 > 知识库问答 >
问题:

JNI库在垃圾收集时释放内存?

羊昊苍
2023-03-14

我正在使用JCUDA,想知道JNI对象是否足够聪明,可以在垃圾收集时解除分配?我能理解为什么这可能在所有情况下都不起作用,但我知道它会在我的情况下起作用,所以我的后续问题是:我如何才能完成这一点?有没有我可以设置的“模式”?我需要构建抽象层吗?或者答案真的是“不,永远不要尝试”,那么为什么不呢?

编辑:我只是指通过JNI创建的本机对象,而不是Java对象。我知道所有Java对象都被平等地对待,即垃圾收集。

共有3个答案

何超英
2023-03-14

这里有两个案例。

  1. 本机代码分配Java对象。这些对象与所有其他Java对象一样都是GC。如果本机搞砸并持有强引用,它可以阻止GC。
  2. 本机代码分配本机内存。气相色谱对此一无所知;由图书馆来安排释放它。一种方法是拥有一个带有终结器的Java对象,该终结器进行必要的JNI调用以释放本机内存。
谷梁凌
2023-03-14

在JNI中创建的Java对象与所有其他Java对象相同,并且在时机成熟时会被垃圾收集和销毁。为了防止这些对象过早被破坏,我们经常使用JNI函数env-

另一方面,本机对象不接受垃圾收集。

刁丰羽
2023-03-14

通常,由于垃圾回收机制,此类库不会释放内存。特别是:JCuda不这样做,也没有选择或“模式”可以这样做。

原因很简单:它不起作用。

您通常会有这样的模式:

void doSomethingWithJCuda()
{
    CUdeviceptr data = new CUdeviceptr();
    cuMemAlloc(data, 1000);

    workWith(data);

    // *(See notes below)
}

在这里,本机内存被分配,Java对象充当本机内存的“句柄”。

在最后一行,数据对象超出范围。因此,它有资格进行垃圾收集。然而,有两个问题:

1.垃圾收集器将只销毁Java对象,而不会释放使用cuMemAlloc或任何其他本机调用分配的内存。

因此,通常必须通过显式调用来释放本机内存

cuMemFree(data);

在离开方法之前。

2.您不知道Java对象何时会被垃圾收集,也不知道它是否会被垃圾收集。

一个常见的误解是,当对象不再可访问时,它会被垃圾收集,但这不一定是真的。

正如巴古利斯在回答中指出的那样:

一种方法是使用带有终结器的Java对象,该终结器进行必要的JNI调用以释放本机内存。

简单地覆盖这些“句柄”对象的finize()方法,并在那里执行cuMemFree(this)调用,看起来可能是一个可行的选项。例如,JavaCL(一个也允许使用JavaGPU的库,因此在概念上有点类似于JCuda)的作者已经尝试过了。

但它根本不起作用:即使Java对象不再可访问,这并不意味着它将立即被垃圾收集。

您根本不知道什么时候会调用finize()方法。

这很容易导致严重错误:当您有100 MB的GPU内存时,您可以使用10个CUdeviceptr对象,每个对象分配10 MB的内存。您的GPU内存已满。但是对于Java,这几个CUdeviceptr对象只占用了几个字节,并且在应用程序运行期间可能根本不调用finalize()方法,因为JVM根本不需要回收这几个字节的内存。(这里省略了关于黑客解决方法的讨论,比如调用System.gc()等等——底线是:它不起作用)。

因此,回答您的实际问题:JCuda是一个非常低级的库。这意味着您拥有手动内存管理的全部权力,但也负有全部责任。我知道这是“不方便的”。当我开始创建JCuda时,我最初打算将其作为面向对象包装器库的低级后端。但是,为复杂的通用库(如CUDA)创建一个健壮、稳定且普遍适用的抽象层是一项挑战,我不敢处理这样一个项目——最后但并非最不重要的是,因为。。。比如垃圾收集。。。

 类似资料:
  • 我遇到了一个JNI程序随机内存不足的问题。 这是一个32位java程序,它读取文件,进行一些图像处理,通常使用250MB到1GB。然后丢弃所有这些对象,然后程序对通常需要100-250MB的JNI程序进行一系列调用。 当交互运行时,我从未见过问题。但是,当对许多文件连续运行批处理操作时,JNI程序将随机运行内存溢出。它可能对一个或两个文件有内存问题,然后对下一个10个文件运行正常,然后再次出现故障

  • 问题内容: 我有一段代码可以在内存中加载很大的图像。所以打电话似乎是合理的事情 在加载图像之前。据我所知,它毫无问题。 昨天,我决定使用一个名为FindBugs的非常有用的软件来扫描您的代码并报告可能导致错误或通常不建议使用的策略的问题。问题是我提到的这段代码得到了报告。描述是这样的: …强迫垃圾收集;除了基准测试代码外,都非常可疑 并继续阐述: 代码显式调用垃圾回收。除了基准测试中的特定用途外,

  • Kubernetes 垃圾收集器的角色是删除指定的对象,这些对象曾经有但以后不再拥有 Owner 了。 注意:垃圾收集是 beta 特性,在 Kubernetes 1.4 及以上版本默认启用。 Owner 和 Dependent 一些 Kubernetes 对象是其它一些的 Owner。例如,一个 ReplicaSet 是一组 Pod 的 Owner。具有 Owner 的对象被称为是 Owner

  • 本文向大家介绍Java垃圾收集,包括了Java垃圾收集的使用技巧和注意事项,需要的朋友参考一下 示例 C ++方法-新增和删除 在像C ++这样的语言中,应用程序负责管理动态分配的内存所使用的内存。当使用new运算符在C ++堆中创建对象时,需要相应地使用delete运算符来处置该对象: 如果程序忘记了delete一个对象而只是“忘记”了该对象,则关联的内存将丢失给应用程序。这种情况的术语是内存泄

  • JavaScript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。 而在C 和C++之类的语言中,开发人员的一项基本任务就是手工跟踪内存的使用情况,这是造成许多问题的一个根源。在编写JavaScript 程序时,开发人员不用再关心内存使用问题,所需内存的分配以及无用内存的回收完全实现了自动管理。这种垃圾收集机制的原理其实很简单:找出那些不再继续使用的变量,然后释放其

  • 问题内容: 我想向JVM注册一个回调,所以我知道何时进行垃圾回收。有什么办法吗? 编辑:我想这样做,以便可以在应用程序日志中发生垃圾收集时注销,这样我就可以查看它是否与我所看到的问题相关。启用- Xloggc很有帮助,但是将GC日志中的时间(自应用程序启动以来使用秒数)整合到我的主应用程序日志中有点棘手。 编辑2012年4月:从Java7u4开始,您可以从GarbageCollectorMXBea