처음에 - xrath.com 에서 번역됨

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

## 처음에

## 제 1 장

이 장에서는, Java Native Interface (JNI)를 소개합니다. JNI 는, 네이티브 프로그래밍 인터페이스입니다. 이것에 의해, Java 가상 머신 (VM)으로 실행되는 Java 코드가 C, C++, 어셈블리 언어 등 다른 프로그램 언어로 쓰여진 어플리케이션이나 라이브러리와 상호 운용할 수 있게 됩니다.

JNI 의 가장 중요한 이점은, 이것이 기초가 되는 Java VM 의 구현에 어떤 제한도 부과하지 않는다고 하는 것입니다. 그 때문에, Java VM 벤더는 VM 외 부분에 영향을 주지 않고 , JNI 의 지원를 추가할 수 있습니다. 프로그래머는, 1 개의 버젼의 네이티브 어플리케이션 또는 라이브러리를 기술하면, 그것이 JNI 를 지원하는 모든 Java VM 상에서 동작하는 것을 기대할 수 있습니다.

이 장에서는 다음에 대해 설명합니다.

- Java Native Interface 의 개요
- 배경
- 목적
- Java Native Interface 의 어프로치
- JNI 의 프로그래밍
- JDK 1.1. 2 에서의 변경점

## Java Native Interface 의 개요

Java 로 어플리케이션 전체를 기술할 수가 있는 한편으로, Java 만으로는 어플리케이션의 요구를 채울 수 없는 상황도 있습니다. Java 로 어플리케이션 전체를 기술할 수 없는 경우, 프로그래머는 JNI 를 사용해, 「Java 네이티브 메소드」를 기술하는 것으로써, 이러한 상황에 대처할 수 있습니다.

다음에, Java 네이티브 메소드를 사용할 필요가 있는 경우를 몇개인가 가리킵니다.

- 표준 Java 클래스 라이브러리가, 어플리케이션에 필요한 플랫폼 의존 기능을 지원하지 않는 경우
- 다른 언어로 기술된 라이브러리를 벌써 가지고 있어 그 라이브러리로부터 JNI 를 경유해 Java 코드에 액세스 시키는 경우
- 일부의 타임 위기인 코드를 어셈블리등의 저레벨 언어로 구현할 필요가 있는 경우

JNI 를 개입시켜, 프로그래밍에 네이티브 메소드를 사용하는 것으로써, 이하가 가능하게 됩니다.

- Java 객체 (배열과 캐릭터 라인을 포함한다)의 생성, 검사, 갱신
- Java 메소드의 호출
- 예외의 캐치 및 throw
- 클래스의 로드, 및 클래스 정보의 취득
- 실행시의 형태 체크

또, 「호출 API」와(과) 함께 JNI 를 사용하는 것으로써, 임의의 네이티브 어플리케이션에 의한 Java VM 의 매입이 가능하게 됩니다. 이것에 의해, 프로그래머는 VM 원시 코드에 링크하지 않아도, 기존의 어플리케이션을 Java 대응으로 할 수 있습니다.

## 배경

현재, 다른 벤더의 VM 는 다른 네이티브 메소드 인터페이스를 제공합니다. 이러한 다른 인터페이스에 의해, 프로그래머는 주어진 플랫폼에서 복수 버젼의 네이티브 메소드 라이브러리를 생성, 유지, 배포하는 것이 필요하게 됩니다.

기존의 대표적인 네이티브 메소드 인터페이스를 다음에 소개합니다.

- JDK 1.0 네이티브 메소드 인터페이스
- Netscape 의 Java Runtime Interface
- Microsoft 의 Raw Native Interface 및 Java/COM 인터페이스

### JDK 1.0 네이티브 메소드 인터페이스

JDK 1.0 은, 네이티브 메소드 인터페이스를 첨부해 출시되었습니다. 유감스럽지만, 2 개(살)의 큰 이유이기 때문에, 이 인터페이스는 다른 Java VM 에는 적용할 수 없습니다.

제일에, native code는 Java 객체의 필드에 C 구조체의 멤버로서 액세스 합니다. 다만, Java 언어 스펙에서는, 객체를 메모리에 어떻게 배치하는지를 정의하고 있습니다. VM 가 객체를 메모리에 다른 방식으로 배치하는 경우, 프로그래머는 네이티브 메소드 라이브러리를 재컴파일 할 필요가 있습니다.

제니에, JDK 1.0 의 네이티브 메소드 인터페이스는 고전적인 가비지 컬렉터에 의존하고 있습니다. 예를 들어,`unhand` 매크로를 무제한하게 사용하면(자), 네이티브 스택의 고전적인 주사가 필요하게 됩니다.

### Java Runtime Interface

Netscape(TM)는 Java 가상 머신으로 제공되는 서비스의 일반적인 인터페이스인, Java Runtime Interface (JRI)를 제안했습니다. JRI 는 이식성을 고려해 설계되고 있습니다만, 기반이 되는 Java VM 의 구현의 상세한 것에 대하여 충분히 고려되고 있지 않습니다. JRI 는 네이티브 메소드, 데밧깅, 리플렉션, 매입 (호출)등을 포함해, 광범위를 지원하고 있습니다.

### Raw Native Interface 및 Java/COM 인터페이스

Microsoft Java VM 는, 2 개의 네이티브 메소드 인터페이스를 지원합니다. 저레벨에서는, 효율적인 Raw Native Interface (RNI)를 제공합니다. RNI 는, JDK 의 네이티브 메소드 인터페이스와의 소스 레벨의 고도의 하위 호환성을 제공합니다만, 큰 차이가 1 개 있습니다. 엄격한 가베지 컬렉션에 의존하는 대신에, native code는 RNI 기능을 사용해 가비지 컬렉터와 명시적으로 상호 동작하지 않으면 안됩니다.

이것보다 고위의 레벨에서는, Microsoft 의 Java/COM 인터페이스는, 언어에 의존하지 않는 표준 바이너리 인터페이스를 Java VM 에 제공합니다. Java 코드는 COM 객체를 Java 객체인것 같이 사용할 수 있습니다. Java 클래스도 또 COM 클래스로서 시스템의 남은에 개시할 수가 있습니다.

## 목적

충분히 검토된 표준 인터페이스에는, 다음과 같은 이점이 있습니다.

- 각 VM 벤더는 native code의 것보다 큰 본체를 지원할 수 있다
- 트르빌더는, 다른 종류의 네이티브 메소드 인터페이스를 유지할 필요는 없다
- 어플리케이션 프로그래머는, native code의 1 개의 버젼을 쓰는 것만으로 자주(잘), 이 버젼은 다른 VM 상에서 동작한다

표준의 네이티브 메소드 인터페이스를 확립하는 최선의 방법은, Java VM 에 관심이 있는 모든 관계자를 수중에 넣는 것입니다. 이 때문에, 한결같은 네이티브 메소드 인터페이스의 설계에 대해 Java 라이센스 보관 유지자의 사이에 일련의 검토를 실시했습니다. 그것에 의해, 표준의 네이티브 메소드 인터페이스는, 다음의 요건을 채울 필요가 있는 것이 밝혀졌습니다.

- binary level compatibility - 주요한 목표는, 주어진 플랫폼상의 모든 Java VM 구현 전체에서의 네이티브 메소드 라이브러리의 binary level compatibility. 프로그래머는, 1 개의 플랫폼에서 복수의 버젼의 네이티브 메소드 라이브러리를 관리할 수 없습니다.
- 효율 - 타임 위기 코드를 지원하기 위해서는, 네이티브 메소드 인터페이스는 얼마안되는 오버헤드 밖에 부과해서는 안 된다. VM 비의존 ( 및 binary level compatibility)을 보증하는 기존의 기술의 모든 것은, 일정량의 오버헤드를 가져옵니다. 효율성과 VM 비의존동안에서, 어느 정도의 타협을 할 필요가 있습니다.
- 기능성 - 인터페이스는 네이티브 메소드가 유용한 태스크를 달성할 수 있도록(듯이) 하기 위한(해), 충분히 Java 가상 머신의 내부를 개시할 필요가 있다.

## Java Native Interface 의 어프로치

기존의 어프로치의 1 개를 표준 인터페이스로서 적용하는 것은 바람직하다고 생각됩니다. 이것에 의해, 다른 VM 의 복수의 인터페이스를 배울 필요가 있는 프로그래머에게 걸치는 부하는 최저한이 됩니다. 기존의 해결책에서는 이 목표를 완전하게 만족하게 달성하는 것은 존재하지 않았습니다.

Netscape 의 JRI 는, 이식성이 있는 네이티브 메소드 인터페이스로서 가장 가까이에 상정되어 설계의 개시점으로서 사용되어 왔습니다. JRI 에 익숙하고 친하게 지낸 사용자는, API 명명 규칙, 메소드와 필드 ID 의 사용, 로컬 참조와 글로벌 참조의 사용등의 유사성을 알아차리겠지요. 그러나 최선의 노력에 관계없이, VM 는 JRI 및 JNI 의 양쪽 모두를 지원할 수 있습니다만, JNI 는 JRI 와 binary level compatibility가 아닙니다.

Microsoft 의 RNI 는, 네이티브 메소드가 고전적이 아닌 가비지 컬렉터와 협동 작업을 할 때의 문제를 해결하고 있기 (위해)때문에, JDK 1.0 을 개선하고 있다고 말할 수 있습니다. 그러나, RNI 는 VM 비의존 네이티브 메소드 인터페이스로서는 적당하지는 않습니다. JDK 와 같이, RNI 네이티브 메소드는 Java 객체에 C 구조체로서 액세스 합니다. 이 때문에 다음의 2 개의 문제가 발생합니다.

- RNI 는, 내부 Java 객체의 배치를 native code에 개시한다
- C 구조체로서 Java 객체에 직접 액세스 하는 것에 의해, 고도의 가베지 컬렉션 알고리즘으로 필요한 「기입 장벽」을 효율적으로 수중에 넣을 수가 없게 된다.

바이너리 표준으로서 COM 는 다른 VM 간에 완전한 binary level compatibility를 보증합니다. COM 메소드의 기동에는 간접적인 호출만이 필요해, 이 호출은 오버헤드를 거의 따르지 않습니다. 게다가 COM 객체는 버젼 문제의 해결이라고 하는 점으로써 동적 링크 라이브러리에 큰 개선을 가져옵니다.

그러나, 표준 Java 네이티브 메소드 인터페이스로서 COM 를 사용하려면 , 다음의 몇개의 요인이 문제가 됩니다.

- 제일에, Java/COM 인터페이스는, private 필드에의 액세스나 일반적인 예외의 발생 등, 어떤 종류의 필요한 기능을 빠뜨리고 있다
- 제니에, Java/COM 인터페이스는 자동적으로 Java 객체에 대해서 표준의 IUnknown 및 IDispatch COM 인터페이스를 제공해, native code가 public 메소드와 필드를 액세스 할 수 있도록(듯이) 한다. IDispatch 인터페이스는 overload 된 Java 메소드를 취급하지 않고, 메소드명의 조합에서는 대문자와 소문자를 구별하지 않는다. 게다가 IDispatch 인터페이스를 경유해 개시되는 모든 Java 메소드는, 동적형 체크와 강제형 변환을 실행하기 위해서 랩 된다. 이것은, IDispatch 인터페이스가 형지를 무늬를 박아서 염색한 것이 약한 언어 (Basic 등)를 염두에 설계되고 있기 (위해)때문에
- 제3에, 개별의 저레벨 함수를 취급하는 대신에, COM 는 소프트웨어 컴퍼넌트 (독립한 어플리케이션을 포함한다)가 함께 동작하도록(듯이) 설계되고 있다. 모든 Java 클래스 또는 저레벨 네이티브 메소드를 소프트웨어 컴퍼넌트로서 취급하는 것은 적당하지 않다고 생각한다
- 4번째로, COM 는 UNIX 플랫폼상에서 지원되어 있지 않기 때문에, 곧바로는 적용할 수 없다

Java 객체를 COM 객체와 같이 native code에 개시는 하지 않습니다만, JNI 인터페이스 자신은 COM 와 binary level compatibility입니다. COM 가 사용하는 것과 같은 점프 테이블 구조체라고 불러 방편 규칙을 사용합니다. 이것은, COM 의 크로스 플랫폼 지원가 사용 가능하게 되면(자), JNI 는 즉시 Java VM 의 COM 인터페이스가 될 수 있는 것을 의미합니다.

JNI 가, 특정의 Java VM 가 지원하는 유일한 네이티브 메소드 인터페이스여야 한다고는 생각하지 않습니다. 표준 인터페이스는, native code 라이브러리를 다른 Java VM 에 로드하고 싶은 프로그래머를 지원합니다. 어느 케이스에서는, 최고의 효율을 달성하기 위해서, 프로그래머는 저레벨인 VM 고유 인터페이스를 사용할 필요가 있습니다. 다른 케이스에서는, 프로그래머는 고레벨 인터페이스를 사용해, 소프트웨어 컴퍼넌트를 구축할지도 모릅니다. 실제, Java 환경과 컴퍼넌트 소프트웨어 기술이 원숙 해 오는 것에 따라, 네이티브 메소드가 그 중요성을 서서히 잃는 것을 바라고 있습니다.

## JNI 의 프로그래밍

네이티브 메소드 프로그래머는, JNI 의 프로그래밍을 개시할 필요가 있습니다. JNI 의 프로그래밍은, 최종 사용자가 실행하고 있을 가능성이 있는 벤더의 VM 등 미지의 것으로부터 격리해 줍니다. JNI 표준에 준거하는 것으로, 네이티브 라이브러리에 대해서, 특정의 Java VM 로 실행할 수 있을 가능성이 높아집니다. 예를 들어, JDK 1.1 은 JDK 1.0 으로 구현된 낡은 형태의 네이티브 메소드 인터페이스의 지원를 계속합니다만, JDK 의 장래 버젼에서는 낡은 형태의 네이티브 메소드 인터페이스의 지원를 중지하는 것은 확실합니다. 낡은 형식의 인터페이스에 의존하는 네이티브 메소드는 고쳐 쓸 필요가 있습니다.

Java VM 를 구현하는 경우에는, JNI 도 구현할 필요가 있습니다. Java Software 및 사용 허락자는, JNI 가 객체 표현, 가베지 컬렉션 방식등을 포함해 VM 구현에 오버헤드나 제한을 부과하지 않게 최선의 노력을 하고 있습니다. 우리가 간과한 문제를 발견했을 경우에는, 연락해 주십시오.

## JDK 1.1. 2 에서의 변경점

Java Runtime Environment (JRE)를 보다 좋게 지원하기 위해서, JDK 1.1. 2 에서는, 호출 API 의 세세한 점이 확장되었습니다. 이러한 변경에 의해, 기존의 코드를 사용할 수 없게 되는 일이 없습니다. JNI 네이티브 메소드 인터페이스는, 변경되고 있지 않습니다.

- JDK1_1InitArgs 구조체의 reserved0 필드의 이름이, version 로 변경되었다. JDK1_1InitArgs 구조체는, JNI_CreateJavaVM 에의 초기화 인수를 보관 유지한다. JNI_GetDefaultJavaVMInitArgs 및 JNI_CreateJavaVM 의 호출측은, 버젼 필드를 0x00010001 로 설정할 필요가 있다. JNI_GetDefaultJavaVMInitArgs 는, 요구된 버젼이 지원되고 있는지 어떤지를 나타내는 jint 를 돌려주도록(듯이) 변경되었다
- JDK1_1InitArgs 구조체의 reserved1 필드의 이름이, properties 로 변경되었다. 이것은, null 로 끝나는 캐릭터 라인의 배열이다. 각 캐릭터 라인은, 시스템 프로퍼티을 나타내는 다음의 서식을 사용한다

> name=value

시스템 프로퍼티을 나타낸다. 이 기능은, java 커멘드행의 -D 옵션에 상당한다

- Java 1.1. 1 에서는, VM 내의 사용자 thread가, 유일한 DestroyJavaVM 를 호출하는 thread가 아니면 안된다. JDK 1.1. 2 에서는, 이 제약이 제거되었다. 복수의 사용자 thread가 존재할 경우에 DestroyJavaVM 가 불려 갔을 경우는, VM 는, 현재의 thread가 사용자 thread만으로 될 때까지 대기해, 그리고 자기 자신을 파기하려고 한다

목차 | 전의 항목 | 다음의 항목 |

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