Java Object クラスを見ると、次のようなメソッドがいくつか見つかります。
public native int hashCode()
protected native Object clone()
これらのネイティブとは何ですか?これらのメソッドはどのように機能しますか?
Java Object クラスを見ると、次のようなメソッドがいくつか見つかります。
public native int hashCode()
protected native Object clone()
これらのネイティブとは何ですか?これらのメソッドはどのように機能しますか?
他の回答で述べたように、ほとんどのネイティブ メソッドは JNI を使用して実装されています。
ただし、 などのパフォーマンス クリティカルなメソッドObject.hashCode
は通常、組み込み関数として実装されます。バイト コードがマシン コードにコンパイルされると、Java コンパイラはメソッド呼び出しを認識し、適切なコードを直接インライン化します。これは、単純な方法で JNI を使用するよりもはるかに高速であることは明らかです。
Object.hashCode
多くの人は、メモリ内のオブジェクト表現のアドレスを返すと主張します。最新の実装では、オブジェクトは実際にメモリ内を移動します。代わりに、値を格納するためにオブジェクト ヘッダーの領域が使用されます。この値は、値が最初に要求された時点でメモリ アドレスから遅延して導出される場合があります。
これらのネイティブとは何ですか?これらのメソッドはどのように機能しますか?
物事を明確にするための最小限の例:
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 でテスト済み。Oracle JDK 1.8.0_45 でも動作しました。
試してみるGitHub の例。
解釈:
次のことが可能になります。
これは次の目的で使用できます。
移植性が低いというトレードオフがあります。
C から Java を呼び出すこともできますが、最初に C で JVM を作成する必要があります: C++ から Java 関数を呼び出すには?
OpenJDK 8 での例
Object#clone
jdk8u60-b27 で定義されているfind を探してみましょう。
まず、次のことを見つけます。
find . -name Object.java
jdk/src/share/classes/java/lang/Object.java#l212 につながります:
protected native Object clone() throws CloneNotSupportedException;
ここで難しい部分が来ます。すべての間接的な中でクローンがどこにあるかを見つけることです。私を助けたクエリは次のとおりです。
find . -iname object.c
これにより、オブジェクトのネイティブ メソッドを実装している可能性のある C または C++ ファイルが検出されます。jdk/share/native/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");
一連のマクロを展開した後、これが定義点であるという結論に達しました。