JNI参考文献中说
“本地引用在本机方法调用期间有效。它们在本机方法返回后自动释放。
资料来源:http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#global_local
我有点迷路了。根据上述内容,我必须显式调用NewGlobalRef并传递从调用NewObject返回的对象。我试过这个,似乎当GC启动时,它不会收集我的引用(好像有什么东西仍然保留着它们)。考虑以下项目:Main。java:
package lv.example;
import java.io.IOException;
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
ArrayList<Object> store = new ArrayList<Object>();
while(true) {
Object d = null;
try {
int c = System.in.read();
d = Dummy.getWeakGlobalRef();
if(c == 'c')
store.clear();
store.add(d);
System.out.println(d);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
dummy.java:
package lv.example;
class Dummy {
static {
System.loadLibrary("dummy");
}
native static Dummy getLocalRef();
native static Dummy getGlobalRef();
native static Dummy getWeakGlobalRef();
@Override
protected void finalize() throws Throwable {
System.out.println("Finalized");
}
}
libdummy。因此包含本机方法的实现:
JNIEXPORT jobject JNICALL Java_lv_example_Dummy_getLocalRef (JNIEnv *env, jclass cls) {
jmethodID id = env->GetMethodID(cls, "<init>", "()V");
return env->NewObject(cls, id);
}
JNIEXPORT jobject JNICALL Java_lv_example_Dummy_getGlobalRef (JNIEnv *env, jclass cls) {
jmethodID id = env->GetMethodID(cls, "<init>", "()V");
return env->NewGlobalRef(env->NewObject(cls, id));
}
JNIEXPORT jobject JNICALL Java_lv_example_Dummy_getWeakGlobalRef (JNIEnv *env, jclass cls) {
jmethodID id = env->GetMethodID(cls, "<init>", "()V");
return env->NewWeakGlobalRef(env->NewObject(cls, id));
}
主循环显示的行为对我来说似乎很奇怪:1)当我调用getWeakGlobalRef或getLocalRef和clear ArrayList时,GC似乎收集了我创建的所有虚拟对象。2) 当我调用getGlobalRef时,无论是否清除ArrayList,都不会收集任何对象。l
我有点困惑,这是否意味着我可以将本地方法的本地引用返回到Java代码?
对JNI局部引用引用对象;您可以返回对该对象的引用。回到Java方面,“本地引用”没有任何意义。
垃圾收集器的工作原理是从一组根“活动”引用开始,并将从这些引用中可以访问的任何对象标记为“活动”。所有其他对象都会被删除。
JNI的局部和全局引用保存在根引用集中。当创建本地引用的本机方法返回时,本地引用会自动删除。在此之前,您可以(有时也应该)删除本地引用。全局引用由本机代码在任何时候显式创建和删除。
JVM需要知道本机代码是否保留自己对对象的引用。也就是说,如果删除了对象,C/C代码是否仍可能尝试访问它(可能导致segfault)。具有全局引用的对象不会被垃圾收集,因为本机代码表明它可能仍然需要它们。具有本地引用的对象可以被垃圾收集,因为创建引用的函数已经返回到java。具有弱全局引用的对象可以被垃圾收集,因为本机代码已指示它将使用IsSameObject来检查具有弱引用的对象是否已被垃圾收集,以便只有在未被垃圾收集的情况下,它才可以使用该对象正常工作。
关于
所以这意味着,New*Ref仅用于固定本机代码?JVM是否跟踪“本地引用”到我将其分配给Java变量实例的点?
跟踪本地引用,直到返回java。将其分配给java变量不会删除引用,尽管它会独立地阻止该对象的垃圾收集。返回值将在堆栈上具有一个引用,以防止垃圾收集,直到可以将其分配给java变量,因此返回的对象不需要具有全局引用,除非本机代码可能在返回后访问同一对象。如果没有本地引用,JVM可能会在执行JNI函数时对对象进行垃圾收集,因为垃圾收集器在另一个线程中运行。通常不需要显式地将NewRef/DeleteRef调用为
传递给本机方法的所有Java对象(包括作为JNI函数调用结果返回的对象)都会自动添加到注册表中(即给定一个本地引用)。
(引自https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#implementing_local_references)
您可能需要这样做的案例。
本机函数生成一个线程,该线程在原始线程中将控制权返回给java后继续使用该对象。
本机函数将引用的副本存储在某个全局变量中,以便在后续的java调用中使用。
您希望在函数运行时显式删除引用,以在可能需要一段时间的函数期间节省内存。
问题内容: JNI参考资料指出 “本地引用在本地方法调用期间有效。本地方法返回后,它们会自动释放。 来源:http : //docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#global_local 我有点迷路了。根据上述内容,我必须显式调用 NewGlobalRef 并将从调用返回的对象传递给 NewOb
打开命令行,执行: cd ~/desktop mkdir wenjiangs-lemp cd wenjiangs-lemp mkdir app vagrant init centos/7 用编辑器打开 wenjiangs-lemp 目录,编辑 Vagrant 配置文件:Vagrantfile macOS: Vagrant.configure("2") do |config| config.v
我是JNI的新手,我正在努力解决这个问题。 我有一个c回调被网络库(alljoyn)调用。 在这个回调中,我需要调用Java代码。 由于此回调位于另一个线程中,因此我使用以下代码获取JNIEnv指针: (jvm是全局指针) 问题是,当我尝试使用此env指针调用FindClass时,结果为NULL。 如果我在主线程中执行完全相同的FindClass调用,一切都会正常工作。 我怎样才能解决这个问题?这
我的角度控制器中有一个对象数组。 我想返回数组中字段的索引值,该字段具有与我的参数匹配的 ID。 数组中只有一个具有匹配 的对象。
问题内容: 我目前有一种方法可以检查3x3网格中中心项周围的内容,如果8个相邻位置中的内容包含我要检查的内容,我想在长度为7的数组上将该正方形标记为1。 为此,我需要在我的方法中创建并返回一个数组,这可能吗? 问题答案: 不知道是什么问题。你是这个意思?
问题内容: 我有一个方法: 由javah C / C ++头生成的此方法是: 如何从jobject(即ByteBuffer实例)获取数据数组? 问题答案: 假设您使用ByteBuffer.allocateDirect()分配了ByteBuffer,则可以使用GetDirectBufferAddress