Java'daki yerel anahtar kelime ne işe yarar?


Yanıtlar:


343

nativeAnahtar kelime yöntemi JNI (Java Native Interface) kullanarak yerel kodda uygulandığı belirtmek için bir yöntem uygulanır.


3
Gerçek uygulama JNI kullanmak zorunda değildir. Bazı JRE yöntemleri JVM tarafından kendiliğinden ele alınır. Aslında, uygulamanın aslında yerel kod olması bile zorunlu değildir . Sadece “Java programlama dili dışında bir dilde uygulanmaktadır” .
Holger

444

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:

  • Java'dan rastgele derleme koduyla derlenmiş dinamik olarak yüklenmiş bir kitaplığı (burada C ile yazılmış) çağırın
  • sonuçları Java'ya geri alın

Bu aşağıdakiler için kullanılabilir:

  • daha iyi CPU montaj talimatları ile kritik bir bölüme daha hızlı kod yazın (taşınabilir CPU değil)
  • doğrudan sistem çağrıları yapma (işletim sistemi taşınabilir değil)

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.


1
Mükemmel cevap. Yalnızca bir dipnot: static nativeJava yöntemi için, C ++ işlevinin ikinci parametresi türdür jclassve tür değildir jobject.
SR_

@SR_ bilgi için teşekkürler. Cevabımda bir hata mı oldu, yoksa fazladan bir bilgi mi?
Ciro Santilli 法轮功 冠状 病 六四 事件

2
@Ciro, örneğinizle başlayanlar için bazı ekstra bilgiler (SO'da yaklaşık 300'lük bir yanıt referans olarak kullanılabilir). Herhangi bir hata bildirildi (derleme, bağlantı veya çalışma zamanlarında) herhangi bir hata ile yığın üzerinde bir karmaşa denilen yanlış imza ile bir işlevi yaşadım. Bu nedenle, bu adımda dikkatli olmaktan bahsetmeyi önemli buluyorum.
SR_

419

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


3
Bu benim java dosyasında System.currentTimeMillis () (hangi yerel) yazmak benim anlayış ve daha sonra bu çalışmak için, JNI kütüphaneleri veya C veya C ++ veya derleme dilinde yazılmış bazı işlevleri çağıracak ve daha sonra bazı değeri java koduma geri dönecektir . ex: burada currentTimeMillis yöntemi JNI yardımıyla yerel bir kod çağırır ve bu yerel kod sistem kaynağı ile konuşur ex: anakart üzerinde oturan ve böylece dönüş değeri (sistem zamanı) almak bir zamanlayıcı. beni düzeltin lütfen?
MKod

4
@MKod yöntemleri JDK'nın bir 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.
Adam Burley

Bu ifade Yerel anahtar kelime için önemlidir ... 'Yalnızca diğer dilden (genellikle C) erişilebilen sistem veya donanım kaynaklarına erişmeniz gerekir'.
atiqkhaled

@Kidburla "Uygulama JDK kaynak kodunun kendisinde" ile ne demek istediğinizi sorabilir miyim? JNI kullanan currentTimeMillisyerel olarak işaretlendi java.lang.System, değil mi?
flow2k

1
@ flow2k evet, söyledikleriniz muhtemelen doğrudur, neden yorumumda (2 yıldan fazla önce) söylediğimi bilmiyorum
Adam Burley

59

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 . Bir nativeyöntemin gövdesi yalnızca noktalı virgül olarak verilir ve bir blok yerine uygulamanın atlandığını gösterir.


19

SLaks'ın yanıtladığı gibi, nativeanahtar kelime yerel kodu çağırmak içindir.

Ayrıca GWT tarafından javascript yöntemlerini uygulamak için kullanılır .


13

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.

http://en.wikipedia.org/wiki/Java_Native_Interface


8

NATIVE erişilemez değiştiricidir. Yalnızca YÖNTEM'e uygulanabilir. Yöntem veya kodun PLATFORM BAĞIMLI uygulamasını gösterir.


6

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.


6
  • native Java'daki bir anahtar kelimedir, platforma bağımlı olduğunu gösterir.
  • nativeyöntemler Java ( JNI ) ve diğer programlama dilleri arasında arayüz görevi görür .

3

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ı:

  • Yöntem 13 availableProcessors: Yerel olarak etiketlendi ve Kod özelliği yok
  • Yöntem 14 freeMemory: Yerel olarak etiketlendi ve Kod özelliği yok
  • Yöntem 15 totalMemory: Yerel olarak etiketlendi ve Kod özelliği yok
  • Yöntem 16 maxMemory: Yerel olarak etiketlendi ve Kod özelliği yok
  • Yöntem 17 gc: Yerel olarak etiketlendi ve Kod özelliği yok

resim açıklamasını buraya girin

Aslı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:

resim açıklamasını buraya girin

resim açıklamasını buraya girin

Referans

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.