Javaのネイティブキーワードは何ですか?


476

このパズル(Javaキーワードトリビアゲームです)をプレイしているときに、そのnativeキーワードに遭遇しました。

使用されているJavaのネイティブキーワードは何ですか?


回答:


343

nativeキーワードは、この方法は、JNI(Javaのネイティブインタフェース)を使用して、ネイティブコードで実装されていることを示すための方法に適用されます。


3
実際の実装ではJNIを使​​用する必要はありません。特定のJREメソッドは、JVMによって本質的に処理されます。実際、実装が実際にネイティブコードであることは必須ではありません。単に「Javaプログラミング言語以外の言語で実装されている」だけです。
ホルガー

444

最小限の実行可能な例

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 次のことができます。

  • Javaからの任意のアセンブリコードを使用して、コンパイル済みの動的にロードされたライブラリ(ここではCで記述)を呼び出す
  • 結果をJavaに戻す

これは次の目的で使用できます。

  • 優れたCPUアセンブリ命令(CPUポータブルではない)を使用してクリティカルセクションに高速なコードを記述します
  • 直接システムコールを行う(OSポータブルではない)

移植性が低下するというトレードオフがあります。

CからJavaを呼び出すこともできますが、最初にCでJVMを作成する必要があります。C++からJava関数を呼び出す方法は?

類似のネイティブ拡張APIは、PythonNode.jsRubyなどの同じ理由で、他の多くの「VM言語」にも存在します。

Android NDK

概念はこのコンテキストでもまったく同じですが、設定するにはAndroidボイラープレートを使用する必要があります。

公式のNDKリポジトリには、hello-jniアプリなどの「正規」の例が含まれています。

あなたにはAndroidのO上のNDKを使用すると、コンパイル済みの見ることができるネイティブコードの下に対応すること。unzip.apk.solib/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#clonejdk8u60-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");

一連のマクロを拡張した後、これが定義ポイントであるという結論に達します。


1
すばらしい答えです。単なる脚注:static nativeJavaメソッドの場合、C ++関数の2番目のパラメーターはタイプjclassではなくタイプjobjectです。
SR_ 2018年

@SR_情報をありがとう。私の答えに間違いはありましたか、それとも単なる追加情報ですか?
Ciro Santilli郝海东冠状病六四事件法轮功

2
@Ciroそれはあなたの例で始まる人のためのいくつかの追加情報です(SOで約300の答えは参照として役立つかもしれません)。エラーが報告されずに(コンパイル時、リンク時、または実行時のいずれかで)、スタック上の混乱を伴って呼び出された不正なシグネチャを持つ関数がありました。したがって、このステップには注意することが重要です。
SR_

419

メソッドをマークし、Javaではなく他の言語で実装されることを示します。JNI(Java Native Interface)と連動します。

パフォーマンスの重要なセクションを記述するために以前はネイティブメソッドが使用されていましたが、Javaの高速化により、これは一般的ではなくなりました。現在ネイティブメソッドが必要な場合

  • 他の言語で書かれたライブラリをJavaから呼び出す必要があります。

  • 他の言語(通常はC)からのみ到達可能なシステムまたはハードウェアリソースにアクセスする必要があります。実際、実際のコンピューターと対話する多くのシステム関数(ディスクやネットワークIOなど)は、ネイティブコードを呼び出すため、これを実行できます。

参照 Java Native Interface Specification


3
これは私の理解です私がSystem.currentTimeMillis()(これはネイティブです)をJavaファイルに書き込んでからこれが機能するようになりました。例:ここでcurrentTimeMillisメソッドはJNIの助けを借りてネイティブコードを呼び出し、そのネイティブコードはシステムリソースと通信します。例:マザーボード上にあるタイマーと戻り値(システム時間)を取得します。訂正してください。
MKod 2014

4
のような@MKodメソッドcurrentTimeMillisはJDKの一部でありnative、実装はJDKソースコード自体にあるため、注釈が付けられています。実装がアセンブリ言語を使用することはほとんどありません。おそらく、JVMが実行されているオペレーティングシステムのAPIメソッドを呼び出します。たとえば、WindowsではGetSystemTime、kernel32.dllのDLLメソッドを呼び出す場合があります。別のOSでは、実装が異なります。ただし、native(JDKメソッドではなく)作成しているメソッドに使用する場合は、JNIを使​​用して実装を提供する必要があります。
Adam Burley

このステートメントは、Nativeキーワードの重要なステートメントです... '他の言語(通常はC)からのみ到達可能なシステムまたはハードウェアリソースにアクセスする必要があります。
2017

@Kidburla「実装はJDKソースコード自体にある」とはどういう意味ですか? currentTimeMillisはネイティブとしてマークされているjava.lang.Systemため、JNIを使​​用しています。
flow2k 2017

1
@ flow2kはい、あなたが言ったことはおそらく本当です、私がコメントでなぜそれを言ったのかわかりません(2年以上前)
Adam Burley

59

ストレートJava言語仕様

nativeプラットフォームに依存するコードで実装されるメソッド。通常、C、C ++、FORTRAN、またはアセンブリ言語などの別のプログラミング言語で記述されます。nativeメソッドの本体はセミコロンとしてのみ提供され、ブロックの代わりに実装が省略されていることを示します。


19

SLaksが答えたように、 nativeキーワードはネイティブコードを呼び出すためのものです。

また、JavaScriptメソッドを実装するためにGWTによって使用されます。


13

ネイティブコードを実装する関数は、ネイティブとして宣言されます。

Java Native Interface(JNI)は、Java仮想マシン(JVM)で実行されているJavaコードが、ネイティブアプリケーション(ハードウェアおよびオペレーティングシステムプラットフォームに固有のプログラム)と、 C、C ++、アセンブリなどの他の言語。

http://en.wikipedia.org/wiki/Java_Native_Interface


8

NATIVEは非アクセス修飾子です。METHODにのみ適用できます。メソッドまたはコードのプラットフォーム依存の実装を示します。


6

nativeはjavaのキーワードで、実装されていない構造体(メソッド)を抽象化するために使用されますが、ネイティブコードなどのプラットフォームに依存し、Javaスタックではなくネイティブスタックから実行されます。


6
  • native Javaのキーワードであり、プラットフォームに依存することを示します。
  • nativeメソッドは、Java(JNI)と他のプログラミング言語の間のインターフェースとして機能します。

3

ジャワ 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_NATIVE0x0100)のタグが付けられています。これらのメソッドにはCode属性が含まれていません。つまり、これらのメソッドにはRuntime.classファイル内に実際のコーディングロジックがありません。

  • 方法13 availableProcessors:ネイティブとしてタグ付けされ、コード属性なし
  • 方法14 freeMemory:ネイティブとしてタグ付けされ、コード属性なし
  • 方法15 totalMemory:ネイティブとしてタグ付けされ、コード属性なし
  • 方法16 maxMemory:ネイティブとしてタグ付けされ、コード属性なし
  • 方法17 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

ここに画像の説明を入力してください

ここに画像の説明を入力してください

参照

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.