Java 네이티브 인터페이스
Java Native Interface![]() |
소프트웨어 설계에서 Java Native Interface(JNI; Java 네이티브인터페이스)는 Java Virtual Machine(JVM; Java 가상 머신)에서 실행되는 Java 코드가 네이티브 애플리케이션(하드웨어 및 운영 체제 플랫폼 전용 프로그램) 및 C, C++, 어셈블리 등의 다른 언어로 작성된 라이브러리를 호출 및 호출할[1] 수 있도록 하는 외부 함수 인터페이스 프로그래밍 프레임워크입니다.
목적
JNI는 프로그래머가 네이티브 메서드를 작성하여 어플리케이션을 Java 프로그래밍 언어로 완전히 작성할 수 없는 상황을 처리할 수 있도록 합니다.예를 들어 표준 Java 클래스 라이브러리가 플랫폼 고유의 기능이나 프로그램 라이브러리를 지원하지 않는 경우입니다.또한 Java 응용 프로그램에서 액세스할 수 있도록 기존 응용 프로그램(다른 프로그래밍 언어로 작성됨)을 수정하는 데도 사용됩니다.대부분의 표준 라이브러리 클래스는 파일 I/O 및 사운드 기능 등 개발자와 사용자에게 기능을 제공하기 위해 JNI에 의존합니다.표준 라이브러리에 성능 및 플랫폼에 민감한 API 구현을 포함하면 모든 Java 애플리케이션이 안전하고 플랫폼에 의존하지 않는 방식으로 이 기능에 액세스할 수 있습니다.
JNI 프레임워크에서는 Java 코드가 Java 개체를 사용하는 것과 동일한 방식으로 Java 개체를 사용할 수 있습니다.네이티브 메서드는 Java 개체를 만든 다음 이러한 개체를 검사하고 사용하여 작업을 수행할 수 있습니다.네이티브 메서드는 Java 애플리케이션 코드로 작성된 객체를 검사하고 사용할 수도 있습니다.
JNI를 호출할 수 있는 것은 애플리케이션과 서명된 애플릿뿐입니다.
JNI에 의존하는 애플리케이션은 Java가 제공하는 플랫폼 이식성을 잃게 됩니다(일부 회피책은 플랫폼별로 JNI 코드를 개별적으로 구현하여 Java가 운영 체제를 검출하고 실행 시 올바른 운영 체제를 로드하는 것입니다).
자바와의 네이티브 코드 인터페이스뿐만 아니라 자바에서도 그릴 수 있습니다.Canvas
이는 Java AWT 네이티브인터페이스에서 가능합니다.프로세스는 몇 가지 변경 사항만 있을 뿐 거의 동일합니다.Java AWT 네이티브인터페이스는 J2SE 1.3 이후만 사용할 수 있습니다.
또한 JNI는 C [2]브릿지를 통과하지 않고도 어셈블리 코드에 직접 액세스할 수 있습니다.어셈블리에서 Java 응용 프로그램에 액세스하는 것도 같은 [3]방법으로 가능합니다.
설계.
JNI 프레임워크에서 네이티브 함수는 별도의 .c 또는 .cpp 파일로 구현됩니다(C++는 JNI와의 인터페이스를 약간 단순하게 제공합니다).JVM이 함수를 호출할 때 다음 명령을 전달합니다.JNIEnv
포인터, ajobject
포인터 및 Java 메서드에 의해 선언된 Java 인수.예를 들어 Java 문자열을 네이티브 문자열로 변환합니다.
외부 'C' JNIEX 포트 무효 JNICALL Java_ClassName_MethodName (JNIEnv *부러워하다, 작업 대상 obj, 스트링 자바 스트링) { 컨스턴트 차 *네이티브 스트링 = 부러워하다->GetString(스트링)UTFC하스(자바 스트링, 0); //nativeString을 사용하여 작업합니다. 부러워하다->릴리스 문자열UTFC하스(자바 스트링, 네이티브 스트링); }
포인터는 JVM에 대한 인터페이스를 포함하는 구조입니다.JVM과의 상호작용 및 Java 오브젝트 조작에 필요한 모든 기능이 포함되어 있습니다.JNI 함수의 예로는 네이티브 어레이를 Java 어레이로 변환하거나 네이티브 문자열을 Java 문자열로 변환하거나 오브젝트를 인스턴스화하거나 예외를 발생시키는 등이 있습니다.기본적으로 자바 코드가 할 수 있는 모든 것은JNIEnv
훨씬 덜 쉽긴 하지만요.
인수는 이 네이티브메서드가 선언된 Java 객체에 대한 참조입니다.
네이티브 데이터 유형은 Java 데이터 유형 간에 매핑할 수 있습니다.오브젝트, 배열 및 문자열과 같은 복합 타입의 경우 네이티브코드는 에서 메서드를 호출하여 데이터를 명시적으로 변환해야 합니다.JNIEnv
.
JNI 환경 포인터(JNIEnv*)는 Java 메서드에 매핑된 각 네이티브 함수의 인수로 전달되므로 네이티브 메서드 내의 JNI 환경과의 상호작용이 가능합니다.이 JNI 인터페이스 포인터는 저장할 수 있지만 현재 스레드에서만 유효합니다.다른 스레드는 먼저 AttachCurrent를 호출해야 합니다.Thread()를 사용하여 VM에 접속하여 JNI 인터페이스 포인터를 가져옵니다.일단 연결되면 네이티브 스레드는 네이티브 메서드 내에서 실행되는 일반 Java 스레드와 같이 작동합니다.네이티브 스레드는 DetachCurrent를 호출할 때까지 VM에 연결된 상태로 유지됩니다.스레드()[4]를 사용하여 자신을 분리합니다.
JNI 프레임워크는 네이티브 측에서 코드를 실행하여 할당된 비 JVM 메모리 리소스에 대한 자동 가비지 수집을 제공하지 않습니다.따라서 네이티브 사이드 코드(어셈블리 언어 등)는 네이티브 코드가 취득한 메모리 자원을 명시적으로 해방하는 책임을 진다.
Linux 및 Solaris 플랫폼에서는 네이티브코드가 신호 핸들러로 등록되면 JVM을 위한 신호를 대행 수신할 수 있습니다.책임 체인을 사용하여 네이티브 코드를 JVM과 더 잘 상호 운용할 수 있습니다.윈도우즈 플랫폼에서는 시스템(CPU/FPU)에서 생성된 소프트웨어 인터럽트(NULL 포인터 액세스 위반 및 0으로 나누기 작업 등)를 캡처하기 위해 네이티브 코드를 SEH(Structured Exception Handling)를 사용하여 네이티브 코드를 SEH try/catch 블록으로 래핑하고 인터럽트가 다시 JVMi(Je)로 전파되기 전에 이러한 상황을 처리할 수 있습니다.ava 사이드 코드)는 처리되지 않은 [original research?]예외가 발생할 가능성이 높습니다.
NewString에 사용되는 부호화UTF, GetStringUTFLength, GetStringUTFChars, ReleaseStringUTFChars 및 GetStringUTFregion 함수는 "modified UTF-8"[5]입니다.이는 모든 입력에 유효한 UTF-8은 아니지만 실제로는 다른 인코딩입니다.기본 다국어 플레인에 없는 늘 문자(U+0000)와 코드 포인트(U+10000 이상, 즉 UTF-16에서 대리 쌍으로 표현되는 것)는 수정된 UTF-8로 다르게 인코딩됩니다.많은 프로그램이 실제로 이러한 함수를 잘못 사용하여 UTF-8을 표준 UTF 문자열로 반환합니다.UTF-8 스트링 대신 스트링을 사용합니다.프로그램에서는 NewString, GetStringLength, GetStringChars, ReleaseStringChars, GetStringRegion, GetStringCritical 및 ReleaseStringCritical 함수를 사용해야 합니다.이 함수는 리틀엔디안 아키텍처에서는 UTF-16LE 인코딩을 사용하고 빅엔디안 아키텍처에서는 UTF-16BE 및 UT를 사용합니다.
매핑 유형
다음 표에서는 Java(JNI)와 네이티브코드 간의 유형 매핑을 보여 줍니다.
C타입 | 자바 언어 유형 | 묘사 | 서명의 종류 |
---|---|---|---|
부호 없는 문자 uint8_t | 부울런 | 부호 없는 8비트 | Z |
부호 문자 int8_t | j바이트 | 부호 있는 8비트 | B |
부호 없는 쇼트 uint16_t | 챠 | 부호 없는 16비트 | C |
짧다 int16_t | 쇼트 | 부호 있는 16비트 | S |
인트 int32_t | 진트 | 부호 있는 32비트 | I |
오래오래 | 길게 | 부호 있는 64비트 | J |
흘러가다 | 플로트 | 32비트 | F |
이중으로 하다 | 이중 | 64비트 | D |
무효 | V |
게다가 시그니처는"L fully-qualified-class ;"
는, 그 이름으로 일의로 지정된 클래스를 의미합니다.예를 들어 시그니처"Ljava/lang/String;"
클래스를 참조하다java.lang.String
. 또, 프리픽스[
예를 들어 다음과 같은 유형의 배열을 만듭니다.[I
int 배열 유형을 의미합니다.마지막으로, a.void
시그니처는V
코드를 설정합니다.
이 타입들은 서로 교환할 수 있습니다.사용할 수 있다jint
보통 사용하는 장소에서는,int
, 또는 그 반대도 마찬가지입니다.타이프 캐스팅은 필요 없습니다.그러나 Java String과 어레이 간의 네이티브 문자열과 어레이에 대한 매핑은 다릅니다.만약 a가jstring
a에 사용됩니다.char *
코드가 JVM을 [original research?]손상시킬 수 있습니다.
성능
JNI는 다음과 같은 [6]특정 상황에서 상당한 오버헤드 및 성능 손실을 일으킵니다.
- JNI 메서드에 대한 함수 호출은 특히 메서드를 반복적으로 호출할 경우 비용이 많이 듭니다.
- 네이티브 메서드는 JVM에 의해 인라인화되지 않으며 메서드는 이미 컴파일되어 있기 때문에 JIT 컴파일도 할 수 없습니다.
- Java 배열은 네이티브 코드로 액세스하기 위해 복사한 후 나중에 다시 복사할 수 있습니다.비용은 어레이 크기에 따라 선형적일 수 있습니다.
- 메서드가 오브젝트를 전달받았거나 콜백을 해야 하는 경우 네이티브메서드는 JVM에 대해 자체 콜을 발신합니다.네이티브 코드에서 Java 필드, 메서드 및 유형에 액세스하려면 리플렉션과 유사한 것이 필요합니다.시그니처는 문자열로 지정되며 JVM에서 쿼리됩니다.이는 느리고 오류가 발생하기 쉽습니다.
- Java String은 객체이며 길이가 있으며 인코딩되어 있습니다.문자열에 액세스하거나 작성하려면 O(n) 복사본이 필요할 수 있습니다.
대체 수단
Microsoft가 독자적으로 구현한 Java Virtual Machine(Visual J++)은 RNI(Raw Native Interface)라고 불리는 Java에서 네이티브 코드를 호출하는 유사한 메커니즘을 가지고 있었습니다.또한 J/Direct라고 불리는 Windows API와 같이 Java를 인식하지 못하는 기존 네이티브 코드를 쉽게 호출할 수 있었습니다.다만, 이 실장에 관한 Sun-Microsoft 의 소송에 의해, Visual J++ 는 유지 보수되지 않게 되었습니다.
Java 환경 포인터를 사용하여 부기를 작성할 필요가 없었기 때문에 RNI는 JNI보다 사용하기 덜 서툴렀다.대신 모든 Java 개체에 직접 액세스할 수 있습니다.이를 용이하게 하기 위해 Java 클래스에서 헤더 파일을 생성하는 도구를 사용했습니다.마찬가지로 J/Direct는 필요한 중간 네이티브 라이브러리와 JNI를 사용하는 것보다 사용하기 쉬웠습니다.
Java Native Access(JNA)는 Java 프로그램이 JNI를 사용하지 않고 네이티브 공유 라이브러리에 쉽게 액세스할 수 있도록 하는 커뮤니티 개발 라이브러리입니다.
「 」를 참조해 주세요.
레퍼런스
- ^ "Java Native Interface Overview". The Java Native Interface Programmer's Guide and Specification. Retrieved 2018-12-27.
- ^ "Invoking Assembly Language Programs from Java". Java.net. 2006-10-19. Archived from the original on 2008-03-30. Retrieved 2007-10-06.
- ^ "Launch Java Applications from Assembly Language Programs". Java.net. 2006-10-19. Archived from the original on 2007-10-11. Retrieved 2007-10-04.
- ^ Invocation API입니다.Sun Microsystems.https://docs.oracle.com/en/java/javase/11/docs/specs/jni/invocation.html
- ^ "JNI Types and Data Structures".
- ^ "java — What makes JNI calls slow? - Stack Overflow".
참고 문헌
- Gordon, Rob (March 1998). Essential Jni: Java Native Interface (1st ed.). Prentice Hall. p. 498. ISBN 0-13-679895-0.
- Liang, Sheng (June 20, 1999). Java(TM) Native Interface: Programmer's Guide and Specification (1st ed.). Prentice Hall. p. 320. ISBN 0-201-32577-2.
외부 링크
- Oracle JNI 6.0 API 사양
- Java 네이티브 인터페이스: 프로그래머 가이드 및 사양
- Apple에서 XCode로 JNI
- JNI에서의 예외 처리
- Java Link(JNI용 최신 C++17 래퍼)