답변:
native
키워드는 방법은 JNI (Java 원시 인터페이스)를 사용하여 네이티브 코드로 구현되는 것을 나타내는 방법에 적용된다.
최소 실행 가능 예
Main.java
public class Main {
public native int square(int i);
public static void main(String[] args) {
System.loadLibrary("Main");
System.out.println(new Main().square(2));
}
}
Main.c
#include <jni.h>
#include "Main.h"
JNIEXPORT jint JNICALL Java_Main_square(
JNIEnv *env, jobject obj, jint i) {
return i * i;
}
컴파일하고 실행하십시오.
sudo apt-get install build-essential openjdk-7-jdk
export JAVA_HOME='/usr/lib/jvm/java-7-openjdk-amd64'
javac Main.java
javah -jni Main
gcc -shared -fpic -o libMain.so -I${JAVA_HOME}/include \
-I${JAVA_HOME}/include/linux Main.c
java -Djava.library.path=. Main
산출:
4
Ubuntu 14.04 AMD64에서 테스트되었습니다. Oracle JDK 1.8.0_45와 함께 작업했습니다.
GitHub의 예제 입니다.
Java 패키지 / 파일 이름의 밑줄은 다음에 _1
언급 된대로 C 함수 이름으로 이스케이프되어야합니다 . 밑줄을 포함하는 Android 패키지 이름에서 JNI 함수 호출
해석
native
당신이 할 수 있습니다 :
이것은 다음을 위해 사용될 수 있습니다 :
휴대 성이 낮다는 단점이 있습니다.
C에서 Java를 호출 할 수도 있지만 먼저 C : C ++에서 Java 함수를 호출하는 방법 에서 JVM을 작성해야합니다 .
Python , Node.js , Ruby 와 같은 동일한 이유로 여러 가지 "VM 언어"에도 유사한 기본 확장 API가 있습니다 .
안드로이드 NDK
Android 상용구를 사용하여 설정해야한다는 점을 제외하면이 컨텍스트에서 개념은 동일합니다.
공식 NDK 저장소에는 hello-jni 앱과 같은 "표준"예제가 포함되어 있습니다.
당신에 안드로이드 O에 NDK를 사용하면 사전이 컴파일 볼 수 있다는에서 네이티브 코드에 해당합니다 .unzip
.apk
.so
lib/arm64-v8a/libnative-lib.so
TODO 확인 : 또한 file /data/app/com.android.appname-*/oat/arm64/base.odex
공유 라이브러리라고 ART의 Java 파일에 해당하는 AOT 사전 컴파일 된 .dex라고 생각합니다 .Android의 ODEX 파일이란 무엇입니까? 아마 Java는 실제로native
인터페이스 됩니까?
OpenJDK 8의 예
Object#clone
jdk8u60-b27에서 정의 된 위치를 찾으십시오 .
우리는 그것이 native
호출 로 구현되었다는 결론을 내릴 것입니다 .
먼저 우리는 다음을 발견합니다.
find . -name Object.java
이는 리드 우리에게 JDK / SRC / 주 / 클래스 / 자바 / 랭 / Object.java # L212 :
protected native Object clone() throws CloneNotSupportedException;
이제 어려운 부분이 생겨 클론이 모든 간접 경로 가운데 어디에 있는지 찾는 것입니다. 나를 도운 쿼리는 다음과 같습니다.
find . -iname object.c
Object의 기본 메소드를 구현할 수있는 C 또는 C ++ 파일을 찾습니다. 그것은 우리를 인도 JDK / 주 / 기본 / 자바 / 랭 / Object.c # L47 :
static JNINativeMethod methods[] = {
...
{"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone},
};
JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls,
methods, sizeof(methods)/sizeof(methods[0]));
}
그것은 우리를 JVM_Clone
상징으로 인도합니다 .
grep -R JVM_Clone
그러면 핫스팟 /src/share/vm/prims/jvm.cpp#l580으로 연결됩니다 .
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
많은 매크로를 확장 한 후에는 이것이 정의 지점이라는 결론에 도달합니다.
static
native
Java 메소드의 경우 C ++ 함수의 두 번째 매개 변수는 유형이 jclass
아닙니다 jobject
.
Java가 아닌 다른 언어로 구현되도록 메소드를 표시합니다. JNI (Java Native Interface)와 함께 작동합니다.
과거에는 기본 메소드를 사용하여 성능이 중요한 섹션을 작성했지만 Java가 더 빨라짐에 따라 이제는 일반적이지 않습니다. 기본 방법은 현재 필요한 경우
다른 언어로 작성된 Java에서 라이브러리를 호출해야합니다.
다른 언어 (일반적으로 C)에서만 접근 할 수있는 시스템 또는 하드웨어 리소스에 액세스해야합니다. 실제로 실제 컴퓨터 (예 : 디스크 및 네트워크 IO)와 상호 작용하는 많은 시스템 기능은 기본 코드를 호출하기 때문에이 작업 만 수행 할 수 있습니다.
Java Native Interface 사양 도 참조하십시오.
currentTimeMillis
는 JDK의 일부이며 native
구현은 JDK 소스 코드 자체에 있기 때문에 주석이 달린다 . 구현이 어셈블리 언어를 사용하는 경우는 거의 없습니다. 아마도 JVM이 실행되는 운영 체제의 API 메소드를 호출합니다. 예를 들어 Windows GetSystemTime
에서는 kernel32.dll에서 DLL 메서드 를 호출 할 수 있습니다 . 다른 OS에서는 다른 구현이 있습니다. 그러나 native
메소드에 사용할 때는 (JDK 메소드와 달리) JNI를 사용하여 구현을 제공해야합니다.
currentTimeMillis
네이티브로 표시되어 java.lang.System
있습니까?
에서 직선 Java 언어 사양 :
native
플랫폼 종속 코드로 구현되는 방법 으로, 일반적으로 C, C ++, FORTRAN 또는 어셈블리 언어와 같은 다른 프로그래밍 언어로 작성됩니다.native
메소드 의 본문은 세미콜론으로 만 제공되며, 블록 대신 구현이 생략되었음을 나타냅니다.
네이티브 코드를 구현하는 함수는 네이티브로 선언됩니다.
JNI (Java Native Interface)는 JVM (Java Virtual Machine)에서 실행되는 Java 코드가 원시 애플리케이션 (하드웨어 및 운영 체제 플랫폼에 특정한 프로그램) 및 작성된 라이브러리를 호출하고 호출 할 수 있도록하는 프로그래밍 프레임 워크입니다. C, C ++ 및 어셈블리와 같은 다른 언어
native는 java의 키워드로 추상과 같이 구현되지 않은 구조 (메서드)를 만드는 데 사용되지만 네이티브 코드와 같은 플랫폼 종속적이며 Java 스택이 아닌 네이티브 스택에서 실행됩니다.
Java native
메소드는 기능 또는 성능상의 이유로 Java 코드가 OS 고유 코드를 호출하는 메커니즘을 제공합니다.
예:
606 public native int availableProcessors();
617 public native long freeMemory();
630 public native long totalMemory();
641 public native long maxMemory();
664 public native void gc();
에 Runtime.class
있는 OpenJDK 의 해당 파일 JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.class
에서이 메소드를 포함하고 ACC_NATIVE
( 0x0100
)로 태그를 지정 하고이 메소드에는 Code 속성이 포함되어 있지 않습니다. 즉,이 메소드에는 Runtime.class
파일 에 실제 코딩 논리가 없습니다 .
availableProcessors
: 네이티브로 태그가 지정되고 코드 속성이 없음freeMemory
: 네이티브로 태그되고 코드 속성이 없음totalMemory
: 고유 속성으로 태그가 지정되고 코드 속성이 없음maxMemory
: 네이티브로 태그되고 코드 속성이 없음gc
: 네이티브로 태그되고 코드 속성이 없음실제로 코딩 로직은 해당 Runtime.c 파일에 있습니다.
42 #include "java_lang_Runtime.h"
43
44 JNIEXPORT jlong JNICALL
45 Java_java_lang_Runtime_freeMemory(JNIEnv *env, jobject this)
46 {
47 return JVM_FreeMemory();
48 }
49
50 JNIEXPORT jlong JNICALL
51 Java_java_lang_Runtime_totalMemory(JNIEnv *env, jobject this)
52 {
53 return JVM_TotalMemory();
54 }
55
56 JNIEXPORT jlong JNICALL
57 Java_java_lang_Runtime_maxMemory(JNIEnv *env, jobject this)
58 {
59 return JVM_MaxMemory();
60 }
61
62 JNIEXPORT void JNICALL
63 Java_java_lang_Runtime_gc(JNIEnv *env, jobject this)
64 {
65 JVM_GC();
66 }
67
68 JNIEXPORT jint JNICALL
69 Java_java_lang_Runtime_availableProcessors(JNIEnv *env, jobject this)
70 {
71 return JVM_ActiveProcessorCount();
72 }
이러한 C
코딩은 다음 위치 에있는 libjava.so
(Linux) 또는 libjava.dll
(Windows) 파일 로 컴파일됩니다 JAVA_HOME/jmods/java.base.jmod/lib/libjava.so
.
참고