Was sind diese Eingeborenen und wie funktionieren diese Methoden?
Minimal Beispiel Dinge klarer zu machen:
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;
}
Kompilieren und Ausführen:
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
Ausgang:
4
Getestet auf Ubuntu 14.04. Arbeitete auch mit Oracle JDK 1.8.0_45.
Example on GitHub für Sie mit zu spielen.
Interpretation:
Es ermöglicht Ihnen:
- Aufruf eine kompilierte dynamisch geladene Bibliothek (hier in C geschrieben) mit beliebigen Assembler-Code von Java
- und die Ergebnisse zurück in Java
Dies könnte verwendet werden:
- schreiben schnellen Code auf einem kritischen Abschnitt mit einem besseren CPU Montageanleitung (nicht CPU tragbar)
- direkte Systemaufrufe machen (nicht OS portable)
mit dem Kompromiss der unteren Portabilität.
Es ist auch möglich, dass Sie Java von C zu nennen, aber Sie müssen zuerst eine JVM in C: How to call Java functions from C++?
Beispiel in der OpenJDK 8
finden lassen, wo Object#clone
definiert in jdk8u60-b27.
Zuerst finden wir:
find . -name Object.java
, die uns zu jdk/src/share/classes/java/lang/Object.java#l212 führt:
protected native Object clone() throws CloneNotSupportedException;
Jetzt kommt der schwierige Teil, zu finden, wo Klon inmitten all der Indirektheit ist. Die Abfrage, die mir geholfen haben war:
find . -iname object.c
, die entweder C oder C++ Dateien finden würden, die Object nativen Methoden implementieren könnte.Sie führt uns zu 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]));
}
die uns zum JVM_Clone
Symbol führt:
grep -R JVM_Clone
, die uns zu hotspot/src/share/vm/prims/jvm.cpp#l580 führt:
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
Nach ein paar Makros erweitert, wir kommen zu dem Schluss, dass dies der Definitionspunkt ist.
Wenn hashcode() nur von JVM implementiert wird, warum muss es * nativ * sein? Was genau meinst du mit * intrinsisch * hier? – Geek