2009-06-18 9 views

Antwort

90

Die anderen Antworten sind technisch korrekt, aber nicht sehr nützlich für jemanden ohne JNI-Erfahrung. :-)

Normalerweise, damit die JVM Ihre nativen Funktionen findet, müssen sie auf eine bestimmte Weise benannt werden. beispielsweise für java.lang.Object.registerNatives, wird die entsprechende C-Funktion Java_java_lang_Object_registerNatives genannt. Wenn Sie registerNatives (oder besser gesagt die JNI-Funktion RegisterNatives) verwenden, können Sie Ihre C-Funktionen beliebig benennen.

Hier ist der zugehörige C-Code (von OpenJDK 6):

static JNINativeMethod methods[] = { 
    {"hashCode", "()I",     (void *)&JVM_IHashCode}, 
    {"wait",  "(J)V",     (void *)&JVM_MonitorWait}, 
    {"notify",  "()V",     (void *)&JVM_MonitorNotify}, 
    {"notifyAll", "()V",     (void *)&JVM_MonitorNotifyAll}, 
    {"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])); 
} 

(Beachten Sie, dass Object.getClass nicht in der Liste enthalten ist, wird es von den "Standard" Namen Java_java_lang_Object_getClass genannt wird immer noch.) Für die Funktionen aufgelistet, sind die zugehörigen C-Funktionen wie in dieser Tabelle aufgelistet, was praktischer ist als das Schreiben einer Reihe von Weiterleitungsfunktionen. Wenn native Funktionen in Java eingebettet sind und mit Funktionen innerhalb der Anwendung verknüpft werden sollen (im Gegensatz zu einer gemeinsam genutzten Bibliothek), oder wenn die verwendeten Funktionen nicht "exportiert" werden, ist die Registrierung nativer Funktionen ebenfalls nützlich ", da diese normalerweise nicht durch den Standardmethoden-Suchmechanismus gefunden werden. Das Registrieren nativer Funktionen kann auch verwendet werden, um eine native Methode an eine andere C-Funktion "neu zu binden" (nützlich, wenn Ihr Programm beispielsweise das dynamische Laden und Entladen von Modulen unterstützt).

Ich ermutige jeden, die JNI book zu lesen, die darüber und viel mehr spricht. :-)

+1

Sie haben den vollständig dekorierten JNI-Funktionsnamen geschrieben, was ihn verwirrend macht: Ist 'Java_java_lang_Object_registerNatives' automatisch von der VM aufgerufen, oder muss der c/C++ - Code diese Funktion aufrufen und gibt es keinen Bedarf für dieses java gobblygook – Pavel

+0

@Pavel Standardmäßig a Die native Methode 'methodName' in der Klasse' fully.qualified.ClassName' wird unter dem C-Namen 'Java_fully_qualified_ClassName_methodName' gesucht (den Ihr C-seitiger Code exportieren muss). Sie können 'JNIEnv's' RegisterNatives' Methode aufrufen, um diese Verknüpfung zu überschreiben. Mit anderen Worten, wenn Sie "RegisterNatives" nicht zuerst verwenden, ist "all das Java GobblyGook" [sic] erforderlich. –

+0

Ah, ok, also durch den Export von nur 1 Funktion 'Java_java_lang_Object_registerNatives' kann ich tatsächlich alle meine JNI-Sachen verknüpfen, indem ich den Wert von' cls' überprüfe. Ich habe den Teil vermisst, dass registerNatives tatsächlich Teil von Java selbst ist. Also ... wann wird eine Klasse benutzt werden, wie ist die Reihenfolge der Aktionen, die JVM verwendet, um Eingeborene zu verbinden? Es scheint, dass, wenn Natives noch nicht registriert sind (aus C/C++), JVM nach all diesen exportierten Namen sucht, wenn sie nicht vorhanden sind, dann versucht es, Object.registerNatives zu verwenden (oder umgekehrt?). Übrigens, die jni-Buch-Verbindung ist tot. – Pavel

-9

Da Sie den Quellcode zu finden, es zu finden, ist es ziemlich einfach zu raten ist nicht?

Es ist eine native Methode, und es heißt registerNatives, also denke ich, dass es Objekte mit der zugrunde liegenden Plattform registriert.

Es ist auch privat, also ist es wahrscheinlich nichts, worüber man sich Sorgen machen muss.

+20

Sie müssen ein Closed-Source-Programmierer sein ("bewegen Sie sich, nichts zu sehen"), nicht an die Idee von Menschen, die eigentlich wissen wollen, was "unter der Decke" passiert. Genug gesagt. :-P –

+2

Darn, war das offensichtlich, oder? – aberrant80

8

Was etwas verwirrend sein könnte, ist, dass der Code für java.lang.Object.registerNatives in einer früheren Antwort nur ein Beispiel zum Registrieren nativer Funktionen ist. Dies ist der Code, der (in der Implementierung von OpenJDK) native Funktionen für die Klasse Object registriert. Um native Funktionen für Ihre eigene Klasse zu registrieren, müssen Sie die JNI-Funktion RegisterNatives aus dem systemeigenen Code in Ihrer eigenen Bibliothek aufrufen. Das klingt vielleicht ein wenig kreisförmig, aber es gibt mehrere Möglichkeiten, die Schleife zu durchbrechen.

  1. Folgen Sie dem Beispiel dieser Implementierung der Klasse Objekt:

    ein. Deklarieren Sie in Ihrer Java-Klasse eine native Methode (vorzugsweise statisch) mit dem Namen registerNatives (oder einen anderen Namen. Das ist egal).

    b. Definieren Sie in Ihrem systemeigenen Code eine Funktion mit dem Namen Java_<your fully qualified class name>_registerNatives, die einen Aufruf an die JNI-Funktion RegisterNatives enthält.

    c. Stellen Sie sicher, dass in Ihrem Java-Code Ihre Java-Methode registerNatives vor allen Aufrufen anderer systemeigener Methoden aufgerufen wird.

OR

  1. Verwenden JNI_OnLoad

    ein. Definieren Sie in Ihrer nativen Bibliothek eine Funktion jint JNI_OnLoad(JavaVM *vm, void *reserved). Rufen Sie im Hauptteil dieser Funktion die JNI-Funktion RegisterNatives auf.

    b. Die Java-VM sucht automatisch nach JNI_OnLoad und ruft sie ab, wenn Ihre systemeigene Bibliothek von System.loadLibrary geladen wird, den Sie wahrscheinlich bereits aufrufen sollten, wahrscheinlich in einem statischen Initialisierer für Ihre Klasse. (Sie erhalten die erforderliche env Zeiger durch den Aufruf der GetEnv Funktion in der Tabelle, dass die vm Zeiger verweist.)

Verwandte Themen