Podczas gry tę łamigłówkę (jest to gra z ciekawostkami Java), natrafiłem na native
sł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 native
słowo kluczowe.
Do czego służy rodzime słowo kluczowe w Javie?
Odpowiedzi:
Słowo native
kluczowe 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 _1
w 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 unzip
na .apk
z NDK na Androida O, widać skompilowane .so
któ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.odex
mó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 native
interfejs?
Przykład w OpenJDK 8
Znajdźmy gdzie Object#clone
jest zdefiniowany w jdk8u60-b27.
Dochodzimy do wniosku, że jest on realizowany za pomocą native
połą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_Clone
symbolu:
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
native
metody Java drugi parametr funkcji C ++ jest typu, jclass
a 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
currentTimeMillis
są częścią JDK i są opatrzone adnotacjami, native
ponieważ 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 GetSystemTime
w pliku kernel32.dll. W innym systemie operacyjnym będzie miał inną implementację. Jednak jeśli używasz native
metody, którą piszesz (w przeciwieństwie do metody JDK), musisz podać implementację za pomocą JNI.
currentTimeMillis
jest oznaczony jako natywny, java.lang.System
więc używa JNI, prawda?
Prosto z tym Java Language Specification :
Metoda
native
zaimplementowana w kodzie zależnym od platformy, zwykle napisanym w innym języku programowania, takim jak C, C ++, FORTRAN lub język asemblera. Treśćnative
metody 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 native
Metoda 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.class
pliku 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.class
pliku:
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 C
kodowanie jest kompilowany do libjava.so
(Linux) lub libjava.dll
pliku (Windows), znajduje się na JAVA_HOME/jmods/java.base.jmod/lib/libjava.so
:
Odniesienie