Bu bulmaca oynarken (Bu bir Java anahtar kelime trivia oyunu), ben nativeanahtar kelime rastlamak .
Java'daki yerel anahtar kelime ne için kullanılır?
Bu bulmaca oynarken (Bu bir Java anahtar kelime trivia oyunu), ben nativeanahtar kelime rastlamak .
Java'daki yerel anahtar kelime ne için kullanılır?
Yanıtlar:
nativeAnahtar 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 _1belirtildiğ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 unzipbir .apkAndroid O'dan söz NDK ile, önceden derlenmiş görebilirsiniz .sobunun 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.odexART'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 nativearayüz üzerinden de çalışır ?
OpenJDK 8'deki örnek
Burada Object#clonejdk8u60-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_Clonesembole 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 nativeJava yöntemi için, C ++ işlevinin ikinci parametresi türdür jclassve 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
currentTimeMillisparçasıdır nativeve 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 GetSystemTimekernel32.dll'de bir DLL yöntemi çağırabilir . Başka bir işletim sisteminde farklı bir uygulamaya sahip olacaktır. Ancak yazdığınız nativebir yöntem için kullandığınızda (JDK yönteminin aksine) JNI kullanarak uygulamayı sağlamanız gerekir.
currentTimeMillisyerel olarak işaretlendi java.lang.System, değil mi?
Dan Düz Java Dil Şartname :
nativePlatforma bağlı kodda uygulanan, genellikle C, C ++, FORTRAN veya montaj dili gibi başka bir programlama dilinde yazılmış bir yöntem . Birnativeyö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 nativeyö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.classbulunan OpenJDK dosyasını, JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.classbu 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.classdosyası:
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 Ckodlama libjava.so(Linux) veya libjava.dll(Windows) dosyasında derlenmiştir JAVA_HOME/jmods/java.base.jmod/lib/libjava.so:
Referans