2012-11-14 2 views
1

Java 객체의 메서드를 호출 할 수 있어야하는 일부 원시 스레드 (JVM에 연결되지 않음)로 구성된 Android 응용 프로그램이 있습니다.네이티브 멀티 스레딩 및 JNI

이 작업을 수행하는 방법은 관련된 Java 객체에서 호출하는 JNI 함수를 생성하여 필요한 Java 객체 메소드 ID, JNIEnv 및 객체 참조를 정적 네이티브 (* env) -> CallVoidMethod (env, this, JavaMethodID, ...) 등을 사용하여 필요한 메소드에 액세스 할 수 있도록 데이터 구조를 설정합니다.

저는 이것을 확신하지 못합니다. JNIEnv 포인터가 스레드간에 공유 될 수없고 JVM에 연결된 스레드 만이 이런 종류의 작업을 수행 할 수 있다는 것을 알기 때문에 접근 방식이 작동 할 것입니다 ...

실용적인 접근 방법입니까?

+0

는'JNIEnv'은 현재 스레드에 대한 유효 생성 된 글로벌 참조를 제거하는 것을 잊지하지만하지 마십시오 . 그래서 포인터를 저장하고 클래스, 객체, 메소드 ID에 대한 전역 참조를 저장하면됩니다. –

+0

http://developer.android.com/training/articles/perf-jni.html – fadden

답변

2
  1. JNI_OnLoad, 캐시 JavaVM*. 그것은 스레드간에 영구적이며 유효한 유일한 것입니다.
  2. 네이티브 스레드를 설정하자마자 AttachCurrentThread을 호출하고 JNIEnv*을 얻습니다. 이는 단일 스레드에서만 유효합니다.
  3. JavaVM*JNIEnv*jclass입니다. jobjectjmethodID입니다. 이들은 하나의 스레드에 대해서만 유효합니다.
  4. jclass es 및 jobject을 전체 참조로 변환하여 스레드간에 지속되도록합니다. jmethodID은 세계화 될 필요가 없으며 jobject가 아닙니다.
  5. 더 이상의 원시 스레드에서 해당 스레드에 대해 유효한 JNIEnv*을 얻으려면 다시 AttachCurrentThread을 호출해야합니다.
  6. 는 JavaVM` 글로벌 인`당신이 (늦어도 JNI_OnUnload에) 더 이상 필요하지 않을 때
+0

파벨 감사합니다, 이것은 제가 찾고있는 것과 정확히 같습니다. 메소드 ID를 캐시하고 클래스 및 객체 참조를 전역화하면 모든 후속 스레드는 5에서 설명하는 것처럼 자신의 JNIEnv *를 통해 제공되는 동일한 메소드 ID (예 : CallVoidMethod())를 사용할 수 있습니다. 각 스레드마다 메소드 ID를 새로 설정할 필요가 없습니다. –

+0

예, 메소드 ID는 어디에서나 유효합니다. "세계화"는 참조 유형, 즉 jobject에서 파생되는 것에 대해서만 필요합니다. jmethodID는 jobject가 아니며 "[불투명 한 구조] (http://docs.oracle.com/javase/1.3/docs/guide/jni/spec/types.doc.html#1064)"입니다. 내 이론은 클래스의 함수 테이블 (C++의 vtable과 같은)에 대한 순서 색인 일 뿐이므로 클래스의 모든 인스턴스에 대해 동일합니다. –

+0

정말 대단합니다. 다시 고마워요. 귀하의 답변을 '유용함'으로 투표 하겠지만, 아직 충분한 평판을 얻지는 못했습니다. –