Bu bulmaca oynarken (Bu bir Java anahtar kelime trivia oyunu), ben native
anahtar kelime rastlamak .
Java'daki yerel anahtar kelime ne için kullanılır?
Bu bulmaca oynarken (Bu bir Java anahtar kelime trivia oyunu), ben native
anahtar kelime rastlamak .
Java'daki yerel anahtar kelime ne için kullanılır?
Yanıtlar:
native
Anahtar kelime yöntemi JNI (Java Native Interface) kullanarak yerel kodda uygulandığı belirtmek için bir yöntem uygulanır.
Minimal çalıştırılabilir örnek
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;
}
Derleyin ve çalıştırın:
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
Çıktı:
4
Ubuntu 14.04 AMD64 üzerinde test edildi. Ayrıca Oracle JDK 1.8.0_45 ile çalıştı.
Oynamak için GitHub'da örnek .
Java paketi / dosya adlarındaki alt çizgiler, aşağıda _1
belirtildiği gibi C işlev adında kullanılmalıdır: Alt paket içeren Android paket adında JNI işlevlerini çağırmak
yorumlama
native
yapmanıza olanak sağlar:
Bu aşağıdakiler için kullanılabilir:
düşük taşınabilirlik dengesiyle.
Java'yı C'den çağırmanız da mümkündür, ancak önce C'de bir JVM oluşturmanız gerekir: Java işlevlerini C ++ 'dan nasıl çağırırsınız?
Benzer yerel uzantı API'ları aynı nedenlerle, örneğin Python , Node.js , Ruby gibi diğer birçok "VM dilinde" mevcuttur .
Android NDK
Konsept, bu bağlamda tamamen aynıdır, ancak kurmak için Android boilerplate kullanmanız gerekir.
Resmi NDK deposu merhaba-jni uygulaması gibi "kanonik" örnekler içerir:
Sende unzip
bir .apk
Android O'dan söz NDK ile, önceden derlenmiş görebilirsiniz .so
bunun altında yerli koduna karşılık gelir lib/arm64-v8a/libnative-lib.so
.
TODO onayla: ayrıca, file /data/app/com.android.appname-*/oat/arm64/base.odex
ART'ta Java dosyalarına karşılık gelen AOT önceden derlenmiş .dex olduğunu düşündüğüm paylaşılan bir kütüphane olduğunu söylüyor , ayrıca bkz: Android'de ODEX dosyaları nedir? Belki de Java aslında bir native
arayüz üzerinden de çalışır ?
OpenJDK 8'deki örnek
Burada Object#clone
jdk8u60-b27'de tanımlanmış olan yeri bulalım.
Bir native
çağrı ile uygulandığı sonucuna varacağız.
İlk önce şunu buluyoruz:
find . -name Object.java
bu da bizi jdk / src / share / classes / java / lang / Object.java # l212'ye yönlendirir :
protected native Object clone() throws CloneNotSupportedException;
Şimdi zor kısım geliyor, tüm dolaylı yolun ortasında klonun nerede olduğunu bulmak. Bana yardımcı olan sorgu:
find . -iname object.c
bu, Object'in yerel yöntemlerini uygulayabilecek C veya C ++ dosyalarını bulur. Bizi jdk / share / native / java / lang / Object'e götürür. 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]));
}
Bu da bizi JVM_Clone
sembole götürür :
grep -R JVM_Clone
bu da bizi hotspot / src / share / vm / prims / jvm.cpp # l580 adresine yönlendirir :
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
Bir grup makroyu genişlettikten sonra, bunun tanım noktası olduğu sonucuna varıyoruz.
static
native
Java yöntemi için, C ++ işlevinin ikinci parametresi türdür jclass
ve tür değildir jobject
.
Java'da değil, diğer dillerde uygulanacağına dair bir yöntem işaretler. JNI (Java Native Interface) ile birlikte çalışır.
Geçmişte performans açısından kritik bölümler yazmak için yerel yöntemler kullanıldı, ancak Java'nın hızlanmasıyla bu artık daha az yaygın. Şu anda yerel yöntemlere ihtiyaç vardır:
Java'dan başka bir dilde yazılmış bir kitaplığı aramanız gerekir.
Yalnızca diğer dilden (tipik olarak C) erişilebilen sistem veya donanım kaynaklarına erişmeniz gerekir. Aslında, gerçek bilgisayarla (örneğin, disk ve ağ GÇ) etkileşimde bulunan birçok sistem işlevi bunu yalnızca yerel kodu çağırdıkları için yapabilir.
Ayrıca bkz. Java Yerel Arabirim Belirtimi
currentTimeMillis
parçasıdır native
ve uygulama JDK kaynak kodunun kendisinde olduğu için açıklanmaktadır. Uygulamanın montaj dilini kullanması pek olası değildir; muhtemelen JVM'nin üzerinde çalıştığı işletim sisteminin bir API yöntemini çağırır. Örneğin Windows'ta GetSystemTime
kernel32.dll'de bir DLL yöntemi çağırabilir . Başka bir işletim sisteminde farklı bir uygulamaya sahip olacaktır. Ancak yazdığınız native
bir yöntem için kullandığınızda (JDK yönteminin aksine) JNI kullanarak uygulamayı sağlamanız gerekir.
currentTimeMillis
yerel olarak işaretlendi java.lang.System
, değil mi?
Dan Düz Java Dil Şartname :
native
Platforma bağlı kodda uygulanan, genellikle C, C ++, FORTRAN veya montaj dili gibi başka bir programlama dilinde yazılmış bir yöntem . Birnative
yöntemin gövdesi yalnızca noktalı virgül olarak verilir ve bir blok yerine uygulamanın atlandığını gösterir.
yerel kodu uygulayan işlevler yerel olarak bildirilir.
Java Yerel Arabirimi (JNI), bir Java Sanal Makinesi'nde (JVM) çalışan Java kodunun yerel uygulamaları (bir donanım ve işletim sistemi platformuna özgü programlar) ve içinde yazılmış kütüphaneleri çağırmasını ve çağırmasını sağlayan bir programlama çerçevesidir. C, C ++ ve montaj gibi diğer diller.
native, java'da, soyut gibi uygulanmamış bir yapı (yöntem) yapmak için kullanılan bir anahtar kelimedir, ancak yerel kod gibi bir platforma bağımlı olacaktır ve java yığınından değil, yerel yığından yürütülecektir.
Java native
yöntemi, Java kodunun işlevsel veya performans nedeniyle işletim sistemi yerel kodunu çağırması için bir mekanizma sağlar.
Misal:
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();
Mukabil Runtime.class
bulunan OpenJDK dosyasını, JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.class
bu yöntem içermektedir ve bunları etiketli ACC_NATIVE
( 0x0100
) ve içermeyen bu yöntemler Kod özelliği , bu yöntemi anlamına gelir, herhangi bir gerçek kodlama mantığı yok Runtime.class
dosyası:
availableProcessors
: Yerel olarak etiketlendi ve Kod özelliği yokfreeMemory
: Yerel olarak etiketlendi ve Kod özelliği yoktotalMemory
: Yerel olarak etiketlendi ve Kod özelliği yokmaxMemory
: Yerel olarak etiketlendi ve Kod özelliği yokgc
: Yerel olarak etiketlendi ve Kod özelliği yokAslında kodlama mantığı karşılık gelen Runtime.c dosyasındadır:
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 }
Ve bu C
kodlama libjava.so
(Linux) veya libjava.dll
(Windows) dosyasında derlenmiştir JAVA_HOME/jmods/java.base.jmod/lib/libjava.so
:
Referans