Podczas gry tę łamigłówkę (jest to gra z ciekawostkami Java), natrafiłem na nativesłowo kluczowe.
Do czego służy rodzime słowo kluczowe w Javie?
Podczas gry tę łamigłówkę (jest to gra z ciekawostkami Java), natrafiłem na nativesłowo kluczowe.
Do czego służy rodzime słowo kluczowe w Javie?
Odpowiedzi:
Słowo nativekluczowe jest stosowane do metody, aby wskazać, że metoda jest zaimplementowana w kodzie natywnym przy użyciu JNI (Java Native Interface).
Minimalny możliwy do uruchomienia przykład
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;
}
Skompiluj i uruchom:
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
Wynik:
4
Testowany na Ubuntu 14.04 AMD64. Współpracował również z Oracle JDK 1.8.0_45.
Przykład na GitHub, z którym możesz grać.
Podkreślenia w nazwach pakietów / plików Java muszą być poprzedzane znakami ucieczki _1w nazwie funkcji C, jak wspomniano w: Wywoływanie funkcji JNI w nazwie pakietu Android zawierającej podkreślenie
Interpretacja
native pozwala Ci na:
Można to wykorzystać do:
z kompromisem niższej przenośności.
Możliwe jest również wywoływanie Java z C, ale najpierw musisz utworzyć JVM w C: Jak wywoływać funkcje Java z C ++?
Android NDK
W tym kontekście koncepcja jest dokładnie taka sama, z tym wyjątkiem, że do jej skonfigurowania trzeba użyć podstawki Android.
Oficjalne repozytorium NDK zawiera „kanoniczne” przykłady, takie jak aplikacja hello-jni:
W was unzipna .apkz NDK na Androida O, widać skompilowane .soktóry odpowiada natywnego kodu pod lib/arm64-v8a/libnative-lib.so.
TODO potwierdź: co więcej, file /data/app/com.android.appname-*/oat/arm64/base.odexmówi, że jest to biblioteka współdzielona, która, jak myślę, jest wstępnie skompilowaną AOT .dex odpowiadającą plikom Java w ART, zobacz także: Co to są pliki ODEX w Androidzie? Więc może Java jest również uruchamiana przez nativeinterfejs?
Przykład w OpenJDK 8
Znajdźmy gdzie Object#clonejest zdefiniowany w jdk8u60-b27.
Dochodzimy do wniosku, że jest on realizowany za pomocą nativepołączenia.
Najpierw znajdujemy:
find . -name Object.java
co prowadzi nas do jdk / src / share / klas / java / lang / Object.java # l212 :
protected native Object clone() throws CloneNotSupportedException;
Teraz przychodzi trudna część, znalezienie miejsca, w którym klon znajduje się pośród całej pośrednictwa. Zapytanie, które mi pomogło, to:
find . -iname object.c
który znalazłby pliki C lub C ++, które mogłyby implementować rodzime metody Object. Prowadzi nas do 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]));
}
co prowadzi nas do JVM_Clonesymbolu:
grep -R JVM_Clone
co prowadzi nas do hotspot / src / share / vm / prims / jvm.cpp # l580 :
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
Po rozwinięciu kilku makr dochodzimy do wniosku, że jest to punkt definicji.
static nativemetody Java drugi parametr funkcji C ++ jest typu, jclassa nie typu jobject.
Oznacza metodę, że zostanie zaimplementowana w innych językach, a nie w Javie. Współpracuje z JNI (Java Native Interface).
W przeszłości używane były metody rodzime do pisania sekcji krytycznych pod względem wydajności, ale wraz z przyspieszeniem Javy jest to obecnie mniej powszechne. Metody rodzime są obecnie potrzebne, gdy
Musisz wywołać bibliotekę z Java napisaną w innym języku.
Musisz uzyskać dostęp do zasobów systemowych lub sprzętowych, które są dostępne tylko z innego języka (zazwyczaj C). W rzeczywistości wiele funkcji systemowych, które współdziałają z rzeczywistym komputerem (na przykład dyskowe i sieciowe IO), może to zrobić tylko dlatego, że wywołują kod natywny.
Zobacz także specyfikację Java Native Interface
currentTimeMillissą częścią JDK i są opatrzone adnotacjami, nativeponieważ implementacja jest w samym kodzie źródłowym JDK. Jest bardzo mało prawdopodobne, że implementacja używa języka asemblera; prawdopodobnie wywołuje metodę API systemu operacyjnego, na którym działa JVM. Na przykład w systemie Windows może wywoływać metodę DLL GetSystemTimew pliku kernel32.dll. W innym systemie operacyjnym będzie miał inną implementację. Jednak jeśli używasz nativemetody, którą piszesz (w przeciwieństwie do metody JDK), musisz podać implementację za pomocą JNI.
currentTimeMillisjest oznaczony jako natywny, java.lang.Systemwięc używa JNI, prawda?
Prosto z tym Java Language Specification :
Metoda
nativezaimplementowana w kodzie zależnym od platformy, zwykle napisanym w innym języku programowania, takim jak C, C ++, FORTRAN lub język asemblera. Treśćnativemetody jest podawana tylko jako średnik, co oznacza, że implementacja została pominięta zamiast bloku.
funkcje implementujące kod macierzysty są deklarowane jako rodzime.
Java Native Interface (JNI) to platforma programistyczna, która umożliwia uruchamianie kodu Java w maszynie wirtualnej Java (JVM) w celu wywoływania i wywoływania przez aplikacje rodzime (programy specyficzne dla platformy sprzętowej i systemu operacyjnego) oraz biblioteki napisane w inne języki, takie jak C, C ++ i asembler.
native jest słowem kluczowym w java, które służy do tego, aby niezaimplementowana struktura (metoda) była jak abstrakcyjna, ale byłaby zależna od platformy, takiej jak kod natywny i wykonywana ze stosu natywnego, a nie stosu java.
Jawa nativeMetoda zapewnia mechanizm wywoływania przez kod Java natywnego kodu systemu operacyjnego z powodów funkcjonalnych lub wydajnościowych.
Przykład:
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();
W odpowiednim Runtime.classpliku w OpenJDK, znajdującym się w JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.class, zawiera te metody i oznacza je za pomocą ACC_NATIVE( 0x0100), a metody te nie zawierają atrybutu Code , co oznacza, że metody te nie mają żadnej logiki kodowania w Runtime.classpliku:
availableProcessors: oznaczona jako natywna i bez atrybutu KodfreeMemory: oznaczona jako natywna i bez atrybutu KodtotalMemory: oznaczona jako natywna i bez atrybutu KodmaxMemory: oznaczona jako natywna i bez atrybutu Kodgc: oznaczona jako natywna i bez atrybutu KodW rzeczywistości logika kodowania znajduje się w odpowiednim pliku 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 }
A te Ckodowanie jest kompilowany do libjava.so(Linux) lub libjava.dllpliku (Windows), znajduje się na JAVA_HOME/jmods/java.base.jmod/lib/libjava.so:
Odniesienie