gpt4 book ai didi

java - JNI 库在垃圾回收时释放内存?

转载 作者:行者123 更新时间:2023-12-01 16:59:10 24 4
gpt4 key购买 nike

我正在使用 JCUDA,想知道 JNI 对象是否足够智能,可以在垃圾收集时释放它们?我可以理解为什么这可能不适用于所有情况,但我知道它适用于我的情况,所以我的后续问题是:我怎样才能做到这一点?有我可以设置的“模式”吗?我需要构建一个抽象层吗?或者也许答案确实是“不,永远不要尝试”那么为什么不呢?

编辑:我仅指通过 JNI 创建的 native 对象,而不是 Java 对象。我知道所有 Java 对象都被同等对待。垃圾收集。

最佳答案

通常,此类库不会因垃圾回收而释放内存。特别是:JCuda 不这样做,并且没有可以完成此操作的选项或“模式”。

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

您经常会遇到这样的模式:

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

workWith(data);

// *(See notes below)
}

这里,分配了 native 内存,并且Java对象充当该 native 内存的“句柄”。

在最后一行,data 对象超出了范围。因此,它有资格进行垃圾收集。但是,有两个问题:

<小时/>

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

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

cuMemFree(data);

在离开该方法之前。

<小时/>

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

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

bmargulies在他的回答中指出:

One means is to have a Java object with a finalizer that makes the necessary JNI call to free native memory.

简单地重写这些“处理”对象的 finalize() 方法,并在那里执行 cuMemFree(this) 调用,这看起来似乎是一个可行的选择。例如,JavaCL(一个也允许将 GPU 与 Java 一起使用的库,因此在概念上与 JCuda 有点相似)的作者已经尝试过。

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

您根本不知道finalize() 方法何时会被调用。

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

<小时/>

所以回答你的实际问题:JCuda是一个非常低级的库。这意味着您拥有手动内存管理的全部权力,但也承担全部责任。我知道这很“不方便”。当我开始创建 JCuda 时,我最初打算将其作为面向对象的包装器库的低级后端。但是,为像 CUDA 这样的复杂通用库创建一个健壮、稳定且普遍适用的抽象层具有挑战性,而且我不敢处理这样的项目 - 最后但并非最不重要的原因是它的复杂性暗示...诸如垃圾收集之类的事情...

关于java - JNI 库在垃圾回收时释放内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29045116/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com