본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[Java] JNI Invocation API.

by 돼지왕 왕돼지 2012. 3. 22.
반응형



안녕하세요
 돼지왕 왕돼지입니다.


이 글은 Oracle 에서 제공하는 Tutorial 문서를 번역한 것입니다.

출처 :   http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#wp9502 

오늘은 JNI Invocation API에 대해 한번 알아볼까요? 


The Invocation API

Invocation API 는 software vendor 가 Java VM 을 native application 에 올릴 수 있게 해줍니다.Vendor 는 Java VM 소스 코드와의 링크를 하지 않고도 Java-enabled 앱을 출시 할 수 있습니다.

이번 장은 Invocation API 에 대한 overview 로 시작합니다. 그 다음은 Invocation API function 의 reference page 입니다. 


Overview

 
다음 코드 예제는 어떻게 Invocation API 를 사용하는지를 보여줍니다. 이 예제에서 C++ code 는 Java VM 을 만들고 static method 를 호출합니다. 함수 이름은 Min.test 입니다. 깔끔히 보기 위해 error checking 은 생략했습니다.

#include <jni.h>  /* where everything is defined */
...
JavaVM *jvm;  /* denotes a Java VM */
JNIEnv *env;   /* pointer to native method interface */ 

JavaVMOption* options = new JavaVMOption[1];
options[0].optionString = "-Djava.class.path=/usr/lib/java";

JavaVMInitArgs vm_args;  /* JDK/JRE 6 VM initialization arguments */ 
vm_args.version = JNI_VERSION_1_6; 
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;

/* load and initialize a Java VM, return a JNI interface pointer in env */
JNI_CreateJavaVM( &jvm, &env, &vm_args );
delete options;

/* invoke the Main.test method using the JNI */
jclass cls = env->FindClass( "Main" );
jmethodID mid = env->GetStaticMethodID( cls, "test", "(I)V" );
env->CallStaticVoidMethod( cls, mid, 100 );

/* We are done. */
jvm->DestroyJavaVM();


이 예제는 API의 3가지 함수를 사용합니다. Invocation API 는 native application 이 JNI interface pointer 를 사용하여 VM freature 를 사용할 수 있도록 합니다.  디자인은 Netscape의 JRI Embedding Interface 와 비슷합니다.



Creating the VM


JNI_CreateJavaVM() 함수는 Java VM 을 load 하고 초기화합니다. 그리고 JNI interface pointer 에 pointer를 return 합니다. JNI_CreateJavaVM() 을 호출한 thread 는 main thread 로 간주됩니다.



Attaching to the VM


JNI interface pointer (JNIEnv) 는 main thread 에서만 유효합니다. 다른 thread 에서 Java VM 을 접속하려면 반드시 AttachCurrentThread() 를 불러 VM 에 자신을 먼저 붙이고, JNI interface pointer 를 얻어야 합니다. 한번 VM에 붙으면, native thread 는 native 함수에서 보통의 Java thread 처럼 작동합니다. native thread 는 DetachCurrentThread() 를 호출해서 떼어내기 전까지는 계속 VM에 붙은채로 있습니다.

붙어있는 thread 는 적당한 양의 일을 하려면 충분한 stack 공간을 가지고 있어야 합니다. thread 마다 할당하는 stack 공간은 OS 마다 다릅니다. 예를 들어 pthreads 를 이용하면 stack size 는 pthread_attr_t argument 를 pthread_create 에 전달함으로서 결정할 수 있습니다.



Detaching form the VM


VM 에 붙은 native thread는 "반드시" DetachCurrentThread() 를 불러주어 thread가 종료하기 전에 VM 에서 떼 주어야 합니다. thread 는 call stack 에 Java 함수가 있는 한 스스로 떨어지지 않습니다.



Unloading the VM


JNI_DestroyJavaVM() 함수는 Java VM 을 unload 합니다. JDK/JRE 1.1 의 경우는 오직 main thread 만 VM 을 unload 할 수 있습니다. DestroyJavaVM 을 호출함으로서 말이죠. JDK/JRE 1.2 의 경우는 그 제약사항이 없어졌습니다. 어떤 thread 든지 DestoryJavaVM 을 불러 VM 을 unload 할 수 있습니다.

VM 은 현재 thread 가 유일한 non-daemon user thread 일 경우가 될 때까지 기다렸다가 unload 됩니다. User threads 는 Java thread 와 VM 에 붙은 native thread 모두를 이릅니다. 이 제약사항이 있는 이유는 user thread 가 system resource 를 가지고 있을 수 있기 때문입니다. 예를 들면 lock, window 등 말이죠. VM 은 자동으로 그런 resource 들을 free 하지 못합니다. VM 이 unload 할 때 현재 thread 만이 유일한 thread 임을 제약함으로서 thread 들이 가지고 있는 system resource 를 release 하는 것은 프로그래머의 책임이 되었습니다.



Library and Version Management.


JDK/JRE 1.1 의 경우 한번 native library 가 로드되면, 이것은 모든 class loader 에게 보여집니다. 그래서 다른 class loader에 있는 2개의 class는 같은 native method 에 연결될 수 있습니다. 이것은 2가지 문제를 초래합니다.
- 한 class 가 잘못된 native library 와 연결될 수 있습니다. 이건 같은 이름을 가진 다른 class loader 에 의해 불려진 library 일 수 있습니다.
- Native 함수들은 다른 class loader 로 불려진 class 들과 쉽게 섞일 수 있습니다. 이것은 class loader 가 제공하는 name space 구분사항을 어기는 것이며, type safety 문제를 야기합니다.

JDK/JRE 1.2의 경우 매 class loader 가 각자의 native library set 을 관리합니다. 같은 JNI native library 는 한 class loader 에서 두번 이상은 불리지 못합니다. 두번 부르는 것은 UnsatisfiedLinkError 를 야기합니다. 예를 들면 2개의 class loader가 native library 를 load하려 한다면, System.loadLibrary 는 UnsatisfiedLinkError 를 던집니다. 이 새로운 접근법은 다음과 같은 장점이 있습니다.
- class loader 가 제공하는 name space separation 이 native libary 에 적용됩니다. native library 는 다른 class loader 와 섞이지 않습니다.
- 게다가, native library 는 load 한 class loader 가 GC 되면 자동적으로 함께 unload 됩니다.

Version control 이나 resource management 를 사용하기 위해서 JDK/JRE 1.2 버전의 JNI library 는 추가적으로 2개의 function ( JNI_OnLoad, JNI_ONUnload ) 을 지원합니다. ( 자세한 API 문서는 사이트를 참조하세요 )
 


Invocation API Functions


JavaVM type 은 Invocation API function table 의 pointer 입니다. 다음의 코드는 function table 의 예를 보여줍니다.

typedef const struct JNIInvokeInterface *JavaVM;

const struct JNIInvokeInterface ... = {
    NULL,
    NULL,
    NULL,

    DestroyJavaVM,
    AttachCurrentThread,
    DetachCurrentThread,

    GetEnv,

    AttachCurrentThreadAsDaemon
}; 


 JNI_GetDefaultJavaVMInitArgs(), JNI_GetCreatedJavaVMs(), JNI_CreateJavaVM() 3개의 Invocation API 함수는 JavaVM function table 의 일부가 아니라는 점을 주목하세요. 이 함수들은 JavaVM Structure 를 이용하지 않아도 사용할 수 있습니다.

 자세한 API 는 사이트를 참조하세요.




도움이 되셨다면 손가락 꾸욱~





반응형

댓글