回答:
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でも動作しました。
Javaパッケージ/ファイル名の下線_1
は、C関数名でエスケープする必要があります。以下に説明があります:下線を含むAndroidパッケージ名でのJNI関数の呼び出し
解釈
native
次のことができます。
これは次の目的で使用できます。
移植性が低下するというトレードオフがあります。
CからJavaを呼び出すこともできますが、最初にCでJVMを作成する必要があります。C++からJava関数を呼び出す方法は?
類似のネイティブ拡張APIは、Python、Node.js、Rubyなどの同じ理由で、他の多くの「VM言語」にも存在します。
Android NDK
概念はこのコンテキストでもまったく同じですが、設定するにはAndroidボイラープレートを使用する必要があります。
公式のNDKリポジトリには、hello-jniアプリなどの「正規」の例が含まれています。
あなたにはAndroidの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 / share / classes / java / lang / Object.java#l212に移動します。
protected native Object clone() throws CloneNotSupportedException;
ここで難しい部分が来ます。クローンがすべての間接的な中でどこにあるかを見つけます。私を助けたクエリは:
find . -iname object.c
これは、Objectのネイティブメソッドを実装する可能性のあるCまたはC ++ファイルを検出します。それが私たちをリードJDK /共有/ネイティブ/ Javaの/ LANG / 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
これにより、hotspot / src / share / vm / prims / jvm.cpp#l580に移動します。
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
一連のマクロを拡張した後、これが定義ポイントであるという結論に達します。
static
native
Javaメソッドの場合、C ++関数の2番目のパラメーターはタイプjclass
ではなくタイプjobject
です。
メソッドをマークし、Javaではなく他の言語で実装されることを示します。JNI(Java Native Interface)と連動します。
パフォーマンスの重要なセクションを記述するために以前はネイティブメソッドが使用されていましたが、Javaの高速化により、これは一般的ではなくなりました。現在ネイティブメソッドが必要な場合
他の言語で書かれたライブラリをJavaから呼び出す必要があります。
他の言語(通常はC)からのみ到達可能なシステムまたはハードウェアリソースにアクセスする必要があります。実際、実際のコンピューターと対話する多くのシステム関数(ディスクやネットワークIOなど)は、ネイティブコードを呼び出すため、これを実行できます。
currentTimeMillis
はJDKの一部でありnative
、実装はJDKソースコード自体にあるため、注釈が付けられています。実装がアセンブリ言語を使用することはほとんどありません。おそらく、JVMが実行されているオペレーティングシステムのAPIメソッドを呼び出します。たとえば、WindowsではGetSystemTime
、kernel32.dllのDLLメソッドを呼び出す場合があります。別のOSでは、実装が異なります。ただし、native
(JDKメソッドではなく)作成しているメソッドに使用する場合は、JNIを使用して実装を提供する必要があります。
currentTimeMillis
はネイティブとしてマークされているjava.lang.System
ため、JNIを使用しています。
ネイティブコードを実装する関数は、ネイティブとして宣言されます。
Java Native Interface(JNI)は、Java仮想マシン(JVM)で実行されているJavaコードが、ネイティブアプリケーション(ハードウェアおよびオペレーティングシステムプラットフォームに固有のプログラム)と、 C、C ++、アセンブリなどの他の言語。
nativeは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
。
参照