通过调用 API 获取的 JNI 对象引用:本地还是全局?
我正在使用 JNI 调用 API,它在 C 程序中启动 JVM;在这种情况下,您将获得一个 JNIEnv 指针,该指针在您显式销毁 JVM 之前一直有效。 本地/全局区别在这里仍然适用吗?由于 JNIEnv 始终保留在范围内,因此对新创建的对象的本地引用有何含义?
I'm using the JNI invocation API, which starts a JVM within a C program; in this situation, you get a JNIEnv pointer which remains valid until you explicitly destroy the JVM.
Does the local/global distinction still apply here? What's the meaning of a local reference to a newly created object, since the JNIEnv remains in scope all the time?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
JNI 书上对这种情况的描述有点简洁,但是如果你研究得足够久,你就能弄清楚。基本上,当您将本机 C 线程附加到 JVM 时,您将创建一个可以存储一些本地引用的本地上下文。
这些本地引用将永远被释放,除非您使用DeleteLocalRef手动释放它们,或者通过调用DetachThread销毁本地上下文。由于您可能没有对 JVM 执行大量附加和分离操作,因此对您创建的每个本地引用调用 DeleteLocalRef 非常重要。
自然的下一个问题是“如果本地引用在 JVM 分离之前不会被 GC 处理,为什么还要创建全局引用呢?”那么,本地引用不能在线程之间共享。所以你仍然需要创建全局引用来做到这一点。
The JNI book is a little terse about this situation, but you can figure it out if you study it long enough. Basically, when you attach a native C thread to the JVM, you create a local context which can store some local references.
These local references will never be freed until you manually free them with DeleteLocalRef, or you destroy the local context by calling DetachThread. Since you're probably not doing a lot of attaching and detaching to JVMs, it's very important for you to call DeleteLocalRef on every local reference you create.
The natural next question is "why create global refs at all, if local refs don't get GC'ed until the JVM is detached?" Well, local references cannot be shared between threads. So you still have to create global references to do that.
我认为创建 JVM 的线程成为 Java 线程,就像在 Java 中创建或通过 AttachCurrentThread() 附加的任何线程一样,它有其本地堆栈框架。因此,您创建的任何对象都会成为此堆栈帧中的本地引用,当您销毁 JVM(无法分离主线程)或调用 DeleteLocalRef() 时,该对象将过期。
I think the thread which created JVM becomes Java thread, which, like any thread created in Java, or attached via AttachCurrentThread(), has its local stack frame. So any object you create, becomes a local reference in this stack frame, which will expire when you destroy JVM (you can't detach main thread), or call DeleteLocalRef().
据推测,调用 DettachCurrentThread() 也会释放引用。
不幸的是,JNI 规范没有明确定义调用 API 的引用行为,并且实际语义可能取决于特定的 JVM 实现:S
Presumably a call DettachCurrentThread() releases the references as well.
Unfortunately the JNI spec does not clearly define the behavior of references for the invocation API, and it may be that the actual semantics may depend on the specific JVM implementation :S