호출 API - xrath.com 에서 번역됨

목차 | 전의 항목 | Java Native Interface 스펙

## 호출 API

## 제 5 장

이 호출 API 에 의해, 소프트웨어 벤더는 Java VM 를 임의의 네이티브 어플리케이션에 로드할 수 있게 됩니다. 그 벤더의 제공하는 Java 가 실행 가능한 어플리케이션은, Java VM 원시 코드에 링크할 필요가 없습니다.

이 장에서는, 호출 API 의 개요의 설명으로부터 시작합니다. 그 이후는, 모든 호출 API 함수의 레퍼런스 페이지입니다.

Java VM 의 편입 기능을 향상시키기 (위해)때문에, JDK 1.1. 2 의 호출 API 는 몇개의 섬세한 점이 확장되고 있습니다.

## 개요

다음의 코드예에서는, 호출 API 의 함수의 사용 방법에 대해 설명합니다. 이 예에서는, C++ 코드는 Java VM 를 생성해,`Main.test` 로 불리는 static 메소드를 기동합니다. 명확하게 하기 위해서, 에러 체크를 생략 했습니다.

        #include <jni.h>       /* where everything is defined */
        ...
        JavaVM *jvm;       /* denotes a Java VM */
        JNIEnv *env;       /* pointer to native method interface */
        JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */
        vm_args.version = 0x00010001; /* New in 1.1. 2: VM version */
        /* Get the default initialization arguments and set the class
         * path */
        JNI_GetDefaultJavaVMInitArgs(&vm_args);
        vm_args.classpath = ...;
        /* load and initialize a Java VM, return a JNI interface
         * pointer in env */
        JNI_CreateJavaVM(&jvm, &env, &vm_args);
        /* 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 개의 함수를 사용하고 있습니다. 호출 API 는 네이티브 어플리케이션이 JNI 인터페이스 포인터를 사용해 VM 기능에 액세스 할 수 있도록(듯이) 합니다. 이 설계는 Netscape 의 JRI 매입 인터페이스와 같습니다.

### VM 의 생성

`JNI_CreateJavaVM()` 함수는 Java VM 를 로드해 초기화해, JNI 인터페이스 포인터에 포인터를 돌려줍니다. `JNI_CreateJavaVM()` 를 호출한 thread는, 「메인 thread」라고 보입니다.

### VM 에의 접속

JNI 인터페이스 포인터 (`JNIEnv`)는, 현재의 thread에서만 유효합니다. 다른 thread가 Java VM 에 액세스 할 필요가 있는 경우, 이것은 최초로 `AttachCurrentThread()` 를 호출해, 그 자체를 VM 에 접속해 JNI 인터페이스 포인터를 취득할 필요가 있습니다. 한 번 VM 에 접속되면(자), 네이티브 thread는 네이티브 메소드내에서 실행중의 보통 Java thread와 같이 기능합니다. 네이티브 thread는, 그 자체를 분리하기 위해서 `DetachCurrentThread()` 를 호출할 때까지 VM 에 접속된 채로 있습니다.

접속된 thread에는, 적당한 작업량을 실행하기 위한 충분한 스택 영역이 필요합니다. thread마다의 스택 영역의 할당은, operating system 고유합니다. 예를 들어, pthread 를 사용하는 경우는,`pthread_create` 에의 `pthread_attr_t` 인수로 스택 사이즈를 지정할 수가 있습니다.

### VM 의 언로드

메인 thread는, VM 로부터 분리할 수 없습니다. 대신에, VM 전체를 언로드하기 위해서 `DestroyJavaVM()` 를 호출할 필요가 있습니다.

VM 는, 메인 thread가 유일한 사용자 thread가 될 때까지 대기해, 그 후 언로드를 실행합니다. 사용자 thread에는, Java thread 및 접속된 네이티브 thread의 양쪽 모두가 있습니다. 이 제한은, Java thread 또는 접속된 네이티브 thread가 락, 윈도우등의 system resource를 보관 유지하고 있을 가능성이 있기 위해서(때문에) 존재합니다. `VM` 는, 자동적으로 이러한 자원을 해제할 수 없습니다. VM 가 언로드되고 있을 때, 메인 thread를 유일한 실행중의 thread이라고 제한하는 것으로, 임의의 thread가 보관 유지하는 system resource를 해제하는 부하는 프로그래머에게 부과됩니다.

## 초기화 구조체

Java VM 에 따라서 다른 초기화 인수가 필요하게 될 가능성이 있습니다. 현재 및 장래의 모든 Java VM 에 대해, 적절한, 표준의 초기화 구조체를 제공하는 것은 곤란합니다. 타협책으로서 최초의 필드 (version)를 초기화 구조체의 내용 식별용으로 예약해 둡니다. JDK 1.1. 2 를 짜넣은 네이티브 어플리케이션은, 이 버젼 필드를 0x00010001 로 설정할 필요가 있습니다. 구현에 따라서는, JDK 의 지원하는 초기화 인수의 몇개인가를 무시하는 것을 선택할지도 모릅니다만, VM 구현에서는, JDK 와 같은 초기화 구조체를 사용하는 것을 추천합니다.

버젼 번호 0x80000000 에서 0xFFFFFFFF 는 예약되고 있으므로, VM 구현으로 사용할 수 없습니다.

다음의 코드는, JDK 1.1. 2 로 Java VM 의 초기화에 사용되는 구조체를 나타냅니다.

    typedef struct JDK1_1InitArgs {
       /* The first two fields were reserved in JDK 1.1, and
          formally introduced in JDK 1.1. 2.  */
       /* Java VM version */
        jint version;
       /* System properties.  */
        char **properties;
       /* whether to check the Java source files are newer than
        * compiled class files.  */
        jint checkSource;
       /* maximum native stack size of Java-created threads.  */
        jint nativeStackSize;
       /* maximum Java stack size.  */
        jint javaStackSize;
       /* initial heap size.  */
        jint minHeapSize;
       /* maximum heap size.  */
        jint maxHeapSize;
       /* controls whether Java byte code should be verified:
        * 0 -- none, 1 -- remotely loaded code, 2 -- all code.  */
        jint verifyMode;
       /* the local directory path for class loading.  */
        const char *classpath;
       /* a hook for a function that redirects all VM messages.  */
        jint (*vfprintf)(FILE *fp, const char *format,
                         va_list args);
       /* a VM exit hook.  */
        void (*exit)(jint code);
       /* a VM abort hook.  */
        void (*abort)();
       /* whether to enable class GC.  */
        jint enableClassGC;
       /* whether GC messages will appear.  */
        jint enableVerboseGC;
       /* whether asynchronous GC is allowed.  */
        jint disableAsyncGC;
       /* Three reserved fields.  */
        jint reserved0;
        jint reserved1;
        jint reserved2;
    } JDK1_1InitArgs;

JDK 1.1. 2 에서는, 초기화 구조체가 제공하는 훅에 의해, 네이티브 어플리케이션은 VM 메세지를 리다이렉트(redirect) 할 수가 있어 VM 의 종료를 제어할 수가 있게 됩니다.

다음에 나타내는 구조체는, 네이티브 thread가 JDK 1.1. 2 의 Java VM 에 접속할 때, 인수로서 건네받습니다. 실제, 네이티브 thread가 JDK 1.1. 2 에 접속하기 위해서 인수는 필요 없습니다. `JDK1_1AttachArgs` 구조체는, 빈 상태(empty)의 구조체를 허락하지 않는 C 컴파일러용의 매입 슬롯만으로부터 완성됩니다.

    typedef struct JDK1_1AttachArgs {
       /*
        * JDK 1.1 does not need any arguments to attach a
        * native thread.  The padding is here to satisfy the C
        * compiler which does not permit empty structures.
        */
        void *__padding;
    } JDK1_1AttachArgs;

## 라이브러리 및 버젼 관리

JDK 1.1 에서는, 네이티브 라이브러리를 한 번 로드하면(자), 모든 클래스 로더로부터 그 라이브러리를 인식할 수 있었습니다. 그 때문에, 다른 클래스 로더의 2 살의 클래스가, 같은 네이티브 메소드에 링크해 버릴 가능성이 있었습니다. 이 때문에 다음의 2 개의 문제가 발생합니다.

- 어느 클래스는, 다른 클래스 로더내에서 같은 이름을 가지는 클래스가 로드한 네이티브 라이브러리와 잘못해 링크해 버릴 가능성이 있다
- 네이티브 메소드는, 다른 클래스 로더로부터의 클래스와 용이하게 혼동 되어 버리는 일이 있다. 이것에 의해, 클래스 로더에 의해 지정된 이름 공간의 분류가 파괴되어 형태의 안전성의 문제가 일으켜진다

Java 2 SDK 에서는, 각 클래스 로더는, 독자적인 네이티브 라이브러리세트를 관리합니다. 같은 JNI 네이티브 라이브러리를, 2 개(살) 이상의 클래스 로더에 로드할 수 없습니다. 로드하려고 하면(자),`UnsatisfiedLinkError` 가 발생합니다. 예를 들어,`System.loadLibrary` 를 사용해 2 개의 클래스 로더에 네이티브 라이브러리를 로드하려고 하면(자),`UnsatisfiedLinkError` 가 발생합니다. 이 새로운 수법의 이점은 다음과 같습니다.

- 클래스 로더에 근거하는 이름 공간의 분류는, 네이티브 라이브러리에 보관된다. 네이티브 라이브러리는, 다른 클래스 로더로부터의 클래스를 용이하게 혼동 할 것은 없다
- 더해, 네이티브 라이브러리는, 대응하는 클래스 로더의 가베지 컬렉션시에 언로드할 수 있다

버젼 관리 및 자원 관리를 용이하게 하기 위해서, Java 2 플랫폼의 JNI 라이브러리는 다음의 2 개의 함수를 옵션으로 export 할 수가 있습니다.

### JNI_OnLoad

`jint JNI_OnLoad(JavaVM *vm, void *reserved);`

> 네이티브 라이브러리가 로드 되면(자) (예를 들어 `System.loadLibrary` 에 의해), VM 는 `JNI_OnLoad` 를 호출합니다. JNI_OnLoad 는, 네이티브 라이브러리가 필요로 하는 JNI 버젼을 돌려주지 않으면 안됩니다.

> 새로운 JNI 함수의 어떤 것인지를 사용하기 위해서, 네이티브 라이브러리는 `JNI_VERSION_1_2` 를 돌려주는 `JNI_OnLoad` 함수를 export 할 필요가 있습니다. 네이티브 라이브러리가 `JNI_OnLoad` 함수를 export 하지 않는 경우, VM 는 라이브러리가 JNI 버젼 `JNI_VERSION_1_1` 를 요구하고 있는 것만으로 있으면(자) 간주합니다. VM 가 `JNI_OnLoad` 에 의해 반환된 버젼 번호를 인식하지 않는 경우, 네이티브 라이브러리를 로드할 수 없습니다.

##### 링키지:

네이티브 메소드 구현을 포함한 네이티브 라이브러리로부터 export 됩니다.

##### SDK/JRE 1.4 이후:

> > JDK 1.1 으로 이용할 수 있던 JNI 함수에 가세해 J2SE 릴리스 1.2 에 도입된 JNI 함수를 사용하는 경우, 네이티브 라이브러리는 `JNI_VERSION_1_2` 를 돌려주는 `JNI_OnLoad` 함수를 export 할 필요가 있습니다.

> > 릴리스 1.2 로 이용할 수 있던 JNI 함수에 가세해 J2SE 릴리스 1.4 에 도입된 JNI 함수를 사용하는 경우, 네이티브 라이브러리는 `JNI_VERSION_1_4` 를 돌려주는 `JNI_OnLoad` 함수를 export 할 필요가 있습니다.

> > 네이티브 라이브러리가 `JNI_OnLoad` 함수를 export 하지 않는 경우, VM 는 라이브러리가 JNI 버젼 `JNI_VERSION_1_1` 를 요구하고 있는 것만으로 있으면(자) 간주합니다. VM 가 `JNI_OnLoad` 에 의해 반환된 버젼 번호를 인식하지 않는 경우, 네이티브 라이브러리를 로드할 수 없습니다.

> ### JNI_OnUnload

> `void JNI_OnUnload(JavaVM *vm, void *reserved);`

> > 네이티브 라이브러리를 포함한 클래스 로더의 가베지 컬렉션 시에, VM 는 `JNI_OnUnload` 를 호출합니다. 이 함수는, 클린 업 오퍼레이션에 사용됩니다. 이것은 미확인의 문맥 (파이나라이자로부터의 문맥등)으로 불려 가는 함수이므로, 프로그래머는 신중하게 Java VM 서비스를 사용할 필요가 있습니다. 또 Java 콜백을 임의에 실시할리가 없게 하지 않으면 안됩니다.

> `JNI_OnLoad` 와 `JNI_OnUnload` 는, JNI 라이브러리가 옵션으로 제공하는 2 개의 함수이며, VM 로부터 export 되는 것이 아닙니다.

> ##### 링키지:

> 네이티브 메소드 구현을 포함한 네이티브 라이브러리로부터 export 됩니다.

> ##

> ## 호출 API 의 함수

> `JavaVM` 형은 호출해 API 함수 테이블의 포인터입니다. 다음의 코드예에서는, 이 함수 테이블을 나타냅니다.

>     typedef const struct JNIInvokeInterface *JavaVM;

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

>         DestroyJavaVM,
>         AttachCurrentThread,
>         DetachCurrentThread,

>         GetEnv,

>         AttachCurrentThreadAsDaemon
>     };

> 다음의 3 개의 호출 API 함수에 주의해 주세요. `JNI_GetDefaultJavaVMInitArgs()`,`JNI_GetCreatedJavaVMs()`, 및 `JNI_CreateJavaVM()` 는, Java VM 함수가 아닙니다. 이러한 함수는 기존의 `JavaVM` 구조체가 없어도 사용할 수가 있습니다.

> ### JNI_GetDefaultJavaVMInitArgs

> `jint JNI_GetDefaultJavaVMInitArgs(void *vm_args);`

> Java VM 의 디폴트 구성을 돌려줍니다. 이 함수를 호출하기 전에, native code는 vm_args->version 필드를, VM 를 지원할 수 있다고 예측되는 JNI 버젼으로 설정하는1 . JDK 1.1. 2 에서는, vm_args->version 는, 0x00010001 로 설정할 필요가 있습니다. 이 함수로부터 복귀하면(자), vm_args->version 는, VM 가 지원하는 실제의 JNI 버젼으로 설정됩니다.

> ##### 링키지:

> Java 가상 머신을 구현하는 네이티브 라이브러리로부터 export 됩니다.

> ##### 파라미터:

> `vm_args`:디폴트 인수가 들어가는 `VM-specific initialization` 구조체를 참조하는 포인터.

> ##### 반환값:

> 요구된 버젼이 지원되고 있는 경우는 「0」, 요구된 버젼이 지원되어 있지 않은 경우는 부의 수를 돌려줍니다.

> ### JNI_GetCreatedJavaVMs

> `jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen,
> jsize *nVMs);`

> 작성된 Java VM 를 모두 돌려줍니다. VM 에의 포인터는, 작성된 순서에 버퍼 vmBuf 에 기입해집니다. 그러나, 엔트리의 bufLen 번호 밖에 기입하지 않습니다. 작성된 VM 의 전체수는, *nVM 로 돌려줍니다.

> JDK 1.1. 2 는 1 개의 프로세스로, 1 개의 VM 밖에 지원하지 않습니다.

> ##### 링키지:

> Java 가상 머신을 구현하는 네이티브 라이브러리로부터 export 됩니다.

> ##### 파라미터:

> `vmBuf`:VM 구조체가 배치되는 버퍼에의 포인터

> `bufLen`:버퍼의 길이

> `nVMs`:정수를 참조하는 포인터

> ##### 반환값:

> 성공의 경우는 「0」을, 실패의 경우는 부의 수를 돌려줍니다.

> ### JNI_CreateJavaVM

> `jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args);`

> 로드해, Java VM 를 초기화합니다. 현재의 thread가 메인 thread가 됩니다. `env` 인수를, 메인 thread의 JNI 인터페이스 포인터에 설정합니다.

> JDK 1.1 은 1 개의 프로세스로, 1 개의 VM 밖에 지원하지 않습니다. vm_args 의 버젼 필드는, 0x00010001 로 설정할 필요가 있습니다2 .

> JDK 1.1 에서는,`JNI_CreateJavaVM` 에의 2 번째의 인수는 항상 `JNIEnv *` 에의 포인터였습니다. 3 번째의 인수는, JDK 1.1 에 고유의 구조체 (`JDK1_1InitArgs`)에의 포인터입니다. `JDK1_1InitArgs` 구조는, 모든 VM 에 이식성이 있는 것으로서 설계되어 있지 않은 것은 분명합니다.

> Java 2 SDK 에서는, 표준 VM 초기화 구조가 도입됩니다. 하위 호환성은 보관 유지됩니다. VM 초기화 인수가 `JDK1_1InitArgs` 구조를 가리키는 경우,`JNI_CreateJavaVM` 는 JNI 인터페이스 포인터의 1.1 버젼을 돌려줍니다. 3 번째의 인수가 `JavaVMInitArgs` 구조체에 포인트 하는 경우, VM 는, JNI 인터페이스 포인터의 1.2 버젼을 돌려줍니다. 고정 옵션 세트를 포함한 `JDK1_1InitArgs` 와 달리,`JavaVMInitArgs` 는 옵션 캐릭터 라인을 사용해, 임의의 VM 기동 옵션을 encode 합니다.

>     typedef struct JavaVMInitArgs {
>         jint version;

>         jint nOptions;
>         JavaVMOption *options;
>         jboolean ignoreUnrecognized;
>     } JavaVMInitArgs;

> `version` 필드는 `JNI_VERSION_1_2` 로 설정할 필요가 있습니다. (반대로,`JDK1_1InitArgs` 의 버젼 필드는,`JNI_VERSION_1_1` 로 설정할 필요가 있습니다. )`options` 필드는, 다음의 형태의 배열입니다.

>     typedef struct JavaVMOption {
>         char *optionString;
>         void *extraInfo;
>     } JavaVMOption;

> 배열의 사이즈는,`JavaVMInitArgs` 의 nOptions 필드에 나타납니다. ``ignoreUnrecognized` 가 `JNI_TRUE` 의 경우,`JNI_CreateJavaVM` 는, 「`-X`」또는 「`_`」으로 시작되는 모든 인식할 수 없는 옵션 캐릭터 라인을 무시합니다. ignoreUnrecognized` 가 `JNI_FALSE` 로 설정되어 있는 경우,`JNI_CreateJavaVM` 는 인식할 수 없는 옵션 캐릭터 라인에 조우하면(자), 즉시 `JNI_ERR` 를 돌려줍니다. 모든 Java 가상 머신은, 다음의 표준 옵션세트를 인식할 필요가 있습니다.

> > optionString | 설명
> > --- | ---
> > `-D<name>=<value>` | 시스템 프로퍼티을 설정한다
> > `-verbose[:class|gc|jni]` | 장황 출력을 유효하게 한다. 각 옵션의 뒤에, VM 가 인쇄하는 메세지의 종류를 나타내는, 콤마로 단락지은 이름의 리스트를 계속할 수가 있다. 예를 들어, 「`-verbose:gc, class`」는, VM 에 GC 와 클래스 로딩 관련의 메세지를 인쇄하도록(듯이) 지정한다. 표준적인 이름에는,`gc`,`class`, 및 `jni` 등이 있다. 표준이 아닌 (VM 고유의) 이름은 모두, 「`X`」로 시작될 필요가 있다.
> > `vfprintf` | `extraInfo` 는,`vfprintf` 훅에의 포인터
> > `exit` | `extraInfo` 는,`exit` 훅에의 포인터
> > `abort` | `extraInfo` 는,`abort` 훅에의 포인터

> 더해, 각 VM 구현은, 표준이 아닌 독자적인 옵션 캐릭터 라인세트를 지원합니다. 표준이 아닌 옵션명은, 「`-X`」또는 밑줄 ( 「`_`」)로 시작될 필요가 있습니다. 예를 들어, Java 2 SDK 는 `-Xms` 및 `-Xmx` 옵션을 지원하고 있기 (위해)때문에, 프로그래머는 초기 및 최대의 heap 사이즈를 지정할 수 있습니다. `-X`」로 시작되는 옵션은, 「`java`」커멘드행으로부터 액세스 가능합니다.

> 다음의 예는, Java 2 SDK 로 Java 가상 머신을 작성하는 코드입니다.

>     JavaVMInitArgs vm_args;
>     JavaVMOption options[4];

>     options[0]. optionString = "-Djava.compiler=NONE";           /* disable JIT */
>     options[1]. optionString = "-Djava.class.path=c:\myclasses"; /* user classes */
>     options[2]. optionString = "-Djava.library.path=c:\mylibs";  /* set native library path */
>     options[3]. optionString = "-verbose:jni";                   /* print JNI-related messages */

>     vm_args.version = JNI_VERSION_1_2;
>     vm_args.options = options;
>     vm_args.nOptions = 4;
>     vm_args.ignoreUnrecognized = TRUE;

>     /* Note that in the Java 2 SDK, there is no longer any need to call
>      * JNI_GetDefaultJavaVMInitArgs.
>      */
>     res = JNI_CreateJavaVM(&vm, (void **) &env, &vm_args);
>     if (res < 0) ...

> Java 2 SDK 에서는, JDK 1.1 으로 엄밀하게 같은 방법으로 `JDK1_1InitArgs` 를 지원하고 있습니다.

> ##### 링키지:

> Java 가상 머신을 구현하는 네이티브 라이브러리로부터 export 됩니다.

> ##### 파라미터:

> `p_vm`:결과의 VM 구조체가 배치되는 위치에의 포인터

> `p_env`:메인 thread의 JNI 인터페이스 포인터가 배치되는 위치에의 포인터

> `vm_args`:Java VM 초기화 인수

> ##### 반환값:

> 성공의 경우는 「0」을, 실패의 경우는 부의 수를 돌려줍니다.

> ### DestroyJavaVM

> `jint DestroyJavaVM(JavaVM *vm);`

> Java VM 를 언로드해, 그 자원을 회복합니다. 메인 thread만이 VM 를 언로드할 수 있습니다. 시스템은, 메인 thread만이 사용자 thread로서 남을 때까지 대기해, 그 후 VM 를 파기합니다.

> JDK 1.1 에서는,`DestroyJavaVM` 는 완전하게 지원되고 있는 것은 아닙니다. 메인 thread만이 `DestroyJavaVM` 를 호출할 수가 있습니다. Java 2 SDK 에서는, 접속되고 있을까 않은 것처럼 관련되지 않고, 어느 thread도 이 함수를 호출할 수가 있습니다. 현재의 thread가 접속되고 있는 경우, VM 는, 현재의 thread가 유일한 사용자 레벨 Java thread가 될 때까지 대기합니다. 현재의 thread가 접속되어 있지 않은 경우는, VM 가 현재의 thread를 접속해, 현재의 thread가 유일한 사용자 레벨의 thread가 될 때까지 대기합니다. 다만, VM 의 언로드는, Java 2 SDK 에서도 지원되지 않습니다. `DestroyJavaVM` 는, 항상 에러 코드를 돌려줍니다.

> ##### 링키지:

> JavaVM 인터페이스 함수 테이블의 인덱스 3

> ##### 파라미터:

> `vm`:파괴되는 Java VM

> ##### 반환값:

> 성공의 경우는 「0」을, 실패의 경우는 부의 수를 돌려줍니다.

> JDK 1.1. 2 는 VM 의 언로드를 지원하지 않습니다.

> ### AttachCurrentThread

> `jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args);`

> 현재의 thread를 Java VM 에 접속합니다. `JNIEnv` 인수로 JNI 인터페이스 포인터를 돌려줍니다.

> 벌써 접속되고 있는 thread에의 접속은, 무조작입니다.

> 네이티브 thread를 2 개의 Java VM 에 동시에 접속할 수 없습니다.

> thread가 VM 에 접속되고 있는 경우, 문맥 클래스의 로더는, bootstrap loader입니다.

> ##### 링키지:

> JavaVM 인터페이스 함수 테이블의 인덱스 4

> ##### 파라미터:

> `vm`:현재의 thread가 접속되는 VM

> `p_env`:현재의 thread의 JNI 인터페이스 포인터가 배치되는 위치에의 포인터

> `thr_args`:VM 고유의 thread 접속 인수

> JDK 1.1 으로,`AttachCurrentThread` 에의 2 번째의 인수는, 항상 `JNIEnv` 에의 포인터입니다. `AttachCurrentThread` 에의 3 번째의 인수는 예약되고 있어`null` 로 설정하지 않으면 안됩니다.

> Java 2 SDK 로 1.1 의 동작을 시키는 경우에는, 3 번째의 인수로서 `null` 를 건네줍니다. 또는 다음의 구조체에 포인터를 건네주어, 추가 정보를 지정할 수가 있습니다.

> >     typedef struct JavaVMAttachArgs {
> >         jint version;  /* must be JNI_VERSION_1_2 */
> >         char *name;    /* the name of the thread, or NULL */
> >         jobject group; /* global ref of a ThreadGroup object, or NULL */
> >     } JavaVMAttachArgs

> ##### 반환값:

> 성공의 경우는 「0」을, 실패의 경우는 부의 수를 돌려줍니다.

> ### AttachCurrentThreadAsDaemon

> `jint AttachCurrentThreadAsDaemon(JavaVM* vm, void** penv, void* args);`

> `AttachCurrentThread` 와 시멘틱스는 같습니다만, 새롭게 작성 `java.lang.Thread` 인스턴스는 「demon」입니다.

> thread가 벌써 `AttachCurrentThread` 또는 `AttachCurrentThreadAsDaemon` 를 개입시켜 접속되고 있는 경우, 이 루틴은 `penv` 로 포인트 되고 있는 값을 현재의 thread의 `JNIEnv` 로 설정합니다. 이 경우,`AttachCurrentThread` 도 이 루틴도, thread의 「demon」에게 영향을 주지 않습니다.

> ##### 링키지:

> JavaVM 인터페이스 함수 테이블의 인덱스 7.

> ##### 파라미터:

> `vm`:현재의 thread가 접속되는 가상 머신 인스턴스

> `penv`:현재의 thread의 `JNIEnv` 인터페이스 포인터가 배치되는 위치에의 포인터

> `args`:`JavaVMAttachArgs` 구조체에의 포인터

> ##### 반환값

> 성공했을 경우는 0, 실패했을 경우는 부의 수를 돌려줍니다.

> ##### 예외

> 없음

> ##### 도입된 버젼:

> SDK/JRE 1.4

> ### DetachCurrentThread

> `jint DetachCurrentThread(JavaVM *vm);`

> Java VM 로부터 현재의 thread를 분리합니다. 이 thread가 보관 유지하는 Java 모니터는 모두 해제됩니다. 이 thread가 종료하는 것을 기다리는 Java thread 모두에게, 통지를 합니다.

> JDK 1.1 에서는, VM 로부터 메인 thread를 떼어낼 수 없습니다. VM 전체를 언로드하려면 ,`DestroyJavaVM` 를 호출할 필요가 있습니다.

> Java 2 SDK 에서는, VM 로부터 메인 thread를 떼어낼 수가 있습니다.

> Java VM 를 작성하는 thread인 메인 thread를, VM 로부터 분리할 수가 없습니다. 그 대신해, VM 전체를 언로드하기 위해서, 메인 thread는 `JNI_DestroyJavaVM()` 를 호출할 필요가 있습니다.

> ##### 링키지:

> JavaVM 인터페이스 함수 테이블의 인덱스 5.

> ##### 파라미터:

> `vm`:현재의 thread가 분리되는 VM

> ##### 반환값:

> 성공의 경우는 「0」을, 실패의 경우는 부의 수를 돌려줍니다.

> ### GetEnv

> `jint GetEnv(JavaVM *vm, void **env, jint version);`

> ##### 링키지:

> JavaVM 인터페이스 함수 테이블의 인덱스 6.

> ##### 반환값:

> 현재의 thread가 VM 에 접속되어 있지 않은 경우,`*env` 를 `null` 로 설정해,`JNI_EDETACHED` 를 돌려줍니다. 지정한 버젼이 지원되어 있지 않은 경우,`*env` 를 `null` 로 설정해,`JNI_EVERSION` 를 돌려줍니다. 그 이외의 경우는,`*env` 를 적절한 인터페이스로 설정해,`JNI_OK` 를 돌려줍니다.

> ##### 파라미터:

> `vm`:인터페이스 취득원의 가상 머신 인스턴스.
> `env`:현재의 thread의 JNI 인터페이스 포인터의 배치 위치를 참조하는 포인터.
> `version`:요구된 JNI 버젼

> _________________________

> 1. JDK 1.1 에서는, native code로 버젼 필드를 설정할 필요는 없었습니다. 하위 호환이기 때문에, 버젼 필드가 설정되어 있지 않은 경우는, JDK 1.1. 2 는, 요구된 버젼이 0x00010001 라고 상정합니다. JDK 의 장래의 버젼에서는, 버젼 필드를 적절한 값으로 설정할 필요가 있습니다.

> 2. 자세한 것은, 각주 1 을 참조해 주세요.

> 목차 | 전의 항목 |

> Copyright © 2003 Sun Microsystems, Inc. All rights reserved.