원문 : http://java.sun.com/docs/books/jni/html/refs.html
Local Reference
- 대부분의 JNI 함수은 local reference를 생성한다. 예를 들어 NewObject JNI 함수는 새로운 인스턴스를 만들고 인스턴스의 local reference를 반환합니다.
- local reference는 reference를 생성한 native 함수의 동적 context안에서만 유효합니다. 그리고, native 함수의 호출안에서 유효합니다.
- local reference를 static 변수에 저장하면 안됩니다.
- 아래의 예제에서 MyNewString 함수는 local reference의 사용이 잘못되었습니다. stringClass는 static 변수이기 때문에 NewObject로 생성하면 안됩니다. NewGlobalObject로 생성하거나 stringClass는 지역변수가 되어야 합니다.
/* This code is illegal */ jstring MyNewString(JNIEnv *env, jchar *chars, jint len) { static jclass stringClass = NULL; jmethodID cid; jcharArray elemArr; jstring result; if (stringClass == NULL) { stringClass = (*env)->FindClass(env,"java/lang/String"); if (stringClass == NULL) { return NULL; /* exception thrown */ } } /* It is wrong to use the cached stringClass here, because it may be invalid. */ cid = (*env)->GetMethodID(env, stringClass, "", "([C)V"); ... elemArr = (*env)->NewCharArray(env, len); ... result = (*env)->NewObject(env, stringClass, cid, elemArr); (*env)->DeleteLocalRef(env, elemArr); return result; }
- 아래의 코드에서 MyNewString 함수가 local reference를 반환한다면 문제가 발생할 수 있습니다.
JNIEXPORT jstring JNICALL
Java_C_f(JNIEnv *env, jobject this)
{
char *c_str = ...;
...
return MyNewString(c_str);
}
- Local reference는 2가지 방법으로 free가 됩니다. native 함수가 반환되기전에 virtual machine이 자동으로 함수가 수행되는 동안 생성된 모든 local reference를 free합니다. 또한, 프로그래머가 DeleteLocalRef 함수를 명시적으로 호출하여 특정 local reference를 free 할 수 있습니다.
- Local reference는 무효화(invalidated)되기전까지 가비지 컬렉션(Garbage Collection, GC)되지 않습니다.
- DeleteLocalRef 함수로 무효화된 Local reference는 즉시 가비지 컬렉션됩니다.
Global Reference
- Global reference는 여러 native 함수에서 사용할 수 있습니다(전역변수처럼 사용된다능~).
- 프로그래머가 free를 하기 전까지 여러 thread와 native 함수에서 사용될 수 있습니다.
- Global reference도 local reference와 같이 무효화되기전까지는 가비지 컬렉션되지 않습니다.
- Global reference는 NewGlobalRef JNI 함수로만 생성할 수 있습니다.
- DeleteGlobalRef 함수는 global reference를 해제할 때 사용한다. 만약 DeleteGlobalRef 함수의 호출이 실패한다면, Java VM은 reference의 object를 가비지 컬렉션하지 않는다. object가 시스템에서 더 이상 사용되지 않더라도...
- 아래는 Global reference의 사용의 예입니다.
jstring MyNewString(JNIEnv *env, jchar *chars, jint len) { static jclass stringClass = NULL; ... if (stringClass == NULL) { jclass localRefCls = (*env)->FindClass(env, "java/lang/String"); if (localRefCls == NULL) { return NULL; /* exception thrown */ } /* Create a global reference */ stringClass = (*env)->NewGlobalRef(env, localRefCls); /* Is the global reference created successfully? */ if (stringClass == NULL) { return NULL; /* out of memory exception thrown */ } } ... }
Weak Global Reference
- Weak global reference는 NewGlobalWeakRef 함수와 DeleteGlobalWeakRef 함수로 생성하고 해제할 수 있습니다.
- Weak global reference는 globa reference와 동일하게 여러 thread와 native 함수에서 사용될 수 있습니다.
- global reference와 다른 점은 가비지 컬렉션으로부터 기본 object를 유지하지 않습니다.(이게 무슨 말이냐? 가비지 컬렉션이 될 수 있다는 말인데 가비지 컬렉션이 언제되느냐가 weak global reference의 핵심이다. global reference는 DeleteGlobalRef 함수를 호출를 호출하지 않는한 object는 가비지 컬렉션되지 않는다.)
- 아래 예제에서 mypkg.MyCls class이 f 함수는 mypkg.MyCls2 클래스 object의 reference를 저장을 해야 한다. weak global reference에 저장된 class는 mypkg.MyCls2 클래스를 여전히 unload된채로 둔다.(??, 뭥미? 해석이 안됨. ㅠㅠ)
- Java_mypkg_MyCls_f 함수는 MyCls class의 native member method이다.
JNIEXPORT void JNICALL
Java_mypkg_MyCls_f(JNIEnv *env, jobject self)
{
static jclass myCls2 = NULL;
if (myCls2 == NULL) {
jclass myCls2Local =
(*env)->FindClass(env, "mypkg/MyCls2");
if (myCls2Local == NULL) {
return; /* can't find class */
}
myCls2 = NewWeakGlobalRef(env, myCls2Local);
if (myCls2 == NULL) {
return; /* out of memory */
}
}
... /* use myCls2 */
}
- MyCls와 MyCls2는 같은 life time을 가진다고 가정한다.(예를 들어, 두 클래스는 같은 class loader에 의해서 load 되었을것이다.)
- 그래서, 우리는 MyCls와 MyCls의 native method 구현인 Java_mypkg_MyCls_f가 사용인채로 남아 있는 동안에는 MyCls2가 언제 unload 될지, 그리고 나중에 언제 reload 될지에 대한 상황을 고려하지 않는다.
- 만약 myCls2가 unloade가 발생했다면, 우리는 cached weak reference가 여전히 살아있는 class object를 가리키고 있는지, 이미 GC가 된 object를 가리키고 있는지 반드시 검사해야만 한다.
Comparing Reference
- 2개의 Local, global, or weak global reference가 있을 때, reference에 object가 같은지 검사하는 하는 방법은 아래와 같다.
- (*env)->IsSameObject(env, obj1, obj2)
- JNI_TRUE(or 1)이 반환되면, 두 reference는 같은 object를 참조한다.
- JNI_FALSE(or 0)이 반환되면, 두 reference는 다른 object를 참조한다.
- Weak global reference는 다른 규칙이 있다. weak reference가 null object를 참조할 경우에는 object는 GC가 되었다는 것이다.
- (*env)->IsSameObject(env, wobj, NULL)
- 반환값이 JNI_TRUE이면 weak reference가 참조하는 object는 GC가 되었다는 것이다.
- 반환값이 JNI_FALSE면 weak reference는 여전히 유효한(살아있는) object를 참조한다.
댓글 없음:
댓글 쓰기