Vla*_*ovs 1 java java-native-interface garbage-collection jnienv
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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
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");
}
}
Run Code Online (Sandbox Code Playgroud)
libdummy.so包含本机方法的实现:
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));
}
Run Code Online (Sandbox Code Playgroud)
主循环展示的行为对我来说似乎很奇怪:1)当我调用getWeakGlobalRef或getLocalRef并清除ArrayList时,GC似乎收集了我创建的所有虚拟对象.2)当我调用getGlobalRef时,无论是否清除ArrayList或者没有.l,都不会收集任何对象
我在这里有点困惑,这是否意味着我可以将本地方法的本地引用返回给Java代码?
JVM需要知道本机代码是否保留自己对对象的引用.也就是说,如果对象被删除,C/C++代码是否仍然可以尝试访问它(可能导致段错误).具有全局引用的对象不会被垃圾回收,因为本机代码已指示它可能仍然需要它们.具有本地引用的对象可以被垃圾收集,因为创建引用的函数已经返回到java.具有弱全局引用的对象可以被垃圾收集,因为本机代码已经指示它将使用IsSameObject来检查具有弱引用的对象是否已被垃圾收集,以便仅当它没有被垃圾收集时它才会正确地使用该对象. .
回覆:
那么这意味着,New*Ref仅用于固定本机代码?JVM是否跟踪我将其分配给Java变量实例的点的"本地引用"?
跟踪本地引用,直到返回java.将它分配给java变量不会删除引用,尽管它会独立地防止该对象的垃圾收集.返回的值将在堆栈上有一个引用,防止垃圾收集,直到它可以分配给java变量,因此除非本机代码可能在返回后访问同一个对象,否则不需要返回的对象具有全局引用.如果没有本地引用,JVM可能会在执行JNI函数时对对象进行垃圾收集,因为垃圾收集器在另一个线程中运行.通常,不需要显式调用New Ref/Delete Ref as
传递给本机方法的所有Java对象(包括那些作为JNI函数调用结果返回的对象)都会自动添加到注册表中(即给定本地引用).
您可能需要这样做的案例.
本机函数生成一个线程,该线程在原始线程中将控制权返回给java后继续使用该对象.
本机函数在一些全局变量中存储引用的副本,以便在后续的java调用中使用.
您希望在函数运行时显式删除引用,以在可能需要一段时间的函数期间节省内存.
| 归档时间: |
|
| 查看次数: |
2901 次 |
| 最近记录: |