Untuk apa kata kunci asli di Jawa?

Jawaban:

343

Kata nativekunci diterapkan pada metode untuk menunjukkan bahwa metode ini diterapkan dalam kode asli menggunakan JNI (Java Native Interface).

Slaks
sumber
3
Implementasi aktual tidak harus menggunakan JNI. Metode JRE tertentu ditangani secara intrinsik oleh JVM. Bahkan, itu bahkan tidak wajib bahwa implementasi sebenarnya adalah kode asli . Hanya saja "diimplementasikan dalam bahasa selain bahasa pemrograman Java" .
Holger
444

Contoh runnable minimal

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;
}

Kompilasi dan jalankan:

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

Keluaran:

4

Diuji pada Ubuntu 14.04 AMD64. Juga bekerja dengan Oracle JDK 1.8.0_45.

Contoh di GitHub untuk Anda mainkan.

Menggarisbawahi dalam paket Java / nama file harus lolos dengan _1dalam nama fungsi C seperti yang disebutkan di: Memanggil fungsi JNI dalam nama paket Android yang berisi garis bawah

Penafsiran

native memungkinkan Anda untuk:

  • memanggil perpustakaan yang dikompilasi secara dinamis (di sini ditulis dalam C) dengan kode perakitan sewenang-wenang dari Jawa
  • dan dapatkan hasilnya kembali ke Jawa

Ini dapat digunakan untuk:

  • menulis kode lebih cepat pada bagian kritis dengan instruksi perakitan CPU yang lebih baik (bukan CPU portable)
  • melakukan panggilan sistem langsung (bukan OS portabel)

dengan tradeoff portabilitas yang lebih rendah.

Dimungkinkan juga bagi Anda untuk memanggil Java dari C, tetapi Anda harus terlebih dahulu membuat JVM di C: Bagaimana cara memanggil fungsi Java dari C ++?

API ekstensi asli yang analog juga ada di banyak "bahasa VM" lainnya untuk alasan yang sama, misalnya Python , Node.js , Ruby .

Android NDK

Konsepnya persis sama dalam konteks ini, kecuali bahwa Anda harus menggunakan Android boilerplate untuk memasangnya.

Repositori resmi NDK berisi contoh-contoh "kanonik" seperti aplikasi hello-jni:

Dalam Anda unzipseorang .apkdengan NDK di Android O, Anda dapat melihat pre-compiled .soyang sesuai dengan kode asli di bawah lib/arm64-v8a/libnative-lib.so.

TODO mengkonfirmasi: lebih jauh,, file /data/app/com.android.appname-*/oat/arm64/base.odexmengatakan itu adalah pustaka bersama, yang saya pikir adalah AOT yang telah dikompilasi .dex yang sesuai dengan file Java dalam ART, lihat juga: Apakah file ODEX di Android? Jadi mungkin Java sebenarnya juga dijalankan melalui nativeantarmuka?

Contoh di OpenJDK 8

Mari kita temukan cari di mana Object#clonedidefinisikan dalam jdk8u60-b27.

Kami akan menyimpulkan bahwa itu dilaksanakan dengan nativepanggilan.

Pertama kita temukan:

find . -name Object.java

yang membawa kita ke jdk / src / share / classes / java / lang / Object.java # l212 :

protected native Object clone() throws CloneNotSupportedException;

Sekarang sampai pada bagian yang sulit, menemukan di mana klon berada di tengah semua tipuan. Permintaan yang membantu saya adalah:

find . -iname object.c

yang akan menemukan file C atau C ++ yang mungkin mengimplementasikan metode asli Object. Ini menuntun kita ke jdk / share / asli / 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]));
}

yang membawa kita ke JVM_Clonesimbol:

grep -R JVM_Clone

yang membawa kita ke hotspot / src / share / vm / prims / jvm.cpp # l580 :

JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
    JVMWrapper("JVM_Clone");

Setelah memperluas sekelompok makro, kami sampai pada kesimpulan bahwa ini adalah titik definisi.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
1
Jawaban yang sangat bagus. Hanya catatan kaki: untuk static nativemetode Java, parameter kedua dari fungsi C ++ adalah tipe jclassdan bukan jobject.
SR_
@ SR terima kasih atas informasinya. Apakah ada kesalahan pada jawaban saya, atau hanya info tambahan?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
2
@ Circo, ini adalah info tambahan bagi mereka yang mulai dengan contoh Anda (jawaban dengan sekitar 300 pada SO dapat dijadikan referensi). Saya memiliki fungsi dengan tanda tangan yang salah yang dipanggil dengan kekacauan di stack, tanpa kesalahan dilaporkan (pada saat kompilasi, tautan, atau waktu berjalan apa pun). Karenanya saya merasa perlu untuk menyebutkan untuk berhati-hati pada langkah ini.
SR_
419

Itu menandai metode, bahwa itu akan diimplementasikan dalam bahasa lain, bukan di Jawa. Ini bekerja bersama-sama dengan JNI (Java Native Interface).

Metode asli digunakan di masa lalu untuk menulis bagian kritis kinerja tetapi dengan Java semakin cepat ini sekarang kurang umum. Metode asli saat ini diperlukan ketika

  • Anda perlu memanggil perpustakaan dari Jawa yang ditulis dalam bahasa lain.

  • Anda perlu mengakses sumber daya sistem atau perangkat keras yang hanya dapat dijangkau dari bahasa lain (biasanya C). Sebenarnya, banyak fungsi sistem yang berinteraksi dengan komputer nyata (disk dan IO jaringan, misalnya) hanya dapat melakukan ini karena mereka memanggil kode asli.

Lihat Juga Spesifikasi Antarmuka Asli Java

Orhan Cinar
sumber
3
Ini adalah pemahaman saya, saya menulis System.currentTimeMillis () (yang asli) dalam file java dan kemudian ini berfungsi, JNI akan memanggil library atau beberapa fungsi yang ditulis dalam C atau C ++ atau bahasa assembly dan kemudian mengembalikan beberapa nilai kembali ke kode java saya . mis: di sini, metode currentTimeMillis memanggil kode asli dengan bantuan JNI dan kode asli itu berbicara dengan sumber daya sistem mis: pengatur waktu duduk di motherboard dan dengan demikian mendapatkan nilai balik (waktu sistem). perbaiki saya, tolong?
MKod
4
@MKod metode seperti currentTimeMillisadalah bagian dari JDK dan mereka dijelaskan dengan nativekarena implementasi ada dalam kode sumber JDK itu sendiri. Sangat tidak mungkin implementasi menggunakan bahasa assembly; mungkin memanggil metode API dari sistem operasi yang menjalankan JVM di atas. Sebagai contoh pada Windows, ia dapat memanggil metode DLL GetSystemTimedi kernel32.dll. Pada OS lain itu akan memiliki implementasi yang berbeda. Namun ketika Anda menggunakan nativeuntuk metode yang Anda tulis (sebagai lawan dari metode JDK) Anda harus menyediakan implementasi menggunakan JNI.
Adam Burley
Pernyataan ini penting untuk kata kunci Asli ... 'Anda perlu mengakses sumber daya sistem atau perangkat keras yang hanya dapat dijangkau dari bahasa lain (biasanya C)'.
atiqkhaled
@ Kidburla Bolehkah saya bertanya apa yang Anda maksud dengan "implementasi ada dalam kode sumber JDK itu sendiri"? currentTimeMillisditandai sebagai asli java.lang.Systemsehingga menggunakan JNI, bukankah begitu?
flow2k
1
@ flow2k ya, apa yang Anda katakan mungkin benar, saya tidak yakin mengapa saya mengatakan itu dalam komentar saya (lebih dari 2 tahun yang lalu)
Adam Burley
59

Langsung dari para Jawa Bahasa Spesifikasi :

Metode yang nativediimplementasikan dalam kode yang tergantung pada platform, biasanya ditulis dalam bahasa pemrograman lain seperti C, C ++, FORTRAN, atau bahasa assembly. Badan nativemetode diberikan sebagai titik koma saja, menunjukkan bahwa implementasi dihilangkan, bukan blok.

Pops
sumber
19

Saat SLaks menjawab, nativekata kunci untuk memanggil kode asli.

Ini juga digunakan oleh GWT untuk menerapkan metode javascript.

Melv
sumber
13

fungsi yang mengimplementasikan kode asli dinyatakan sebagai asli.

Java Native Interface (JNI) adalah kerangka kerja pemrograman yang memungkinkan kode Java berjalan di Java Virtual Machine (JVM) untuk memanggil, dan dipanggil oleh, aplikasi asli (program khusus untuk platform sistem perangkat keras dan sistem operasi) dan perpustakaan yang ditulis dalam bahasa lain seperti C, C ++ dan assembly.

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

Adelin
sumber
8

NATIVE adalah Non access modifier.it hanya dapat diterapkan ke METHOD. Ini menunjukkan implementasi metode atau kode PLATFORM-DEPENDENT.

Reetika
sumber
6

asli adalah kata kunci dalam java, yang digunakan untuk membuat struktur (metode) yang tidak diimplementasikan seperti abstrak tetapi akan menjadi platform yang bergantung seperti kode asli dan dieksekusi dari tumpukan asli bukan tumpukan java.

Sarfaraz Ahamad Shaikh
sumber
6
  • native adalah kata kunci dalam java, ini menunjukkan platform dependen.
  • nativemetode bertindak sebagai antarmuka antara Java ( JNI ) dan bahasa pemrograman lainnya.
Premraj
sumber
3

nativeMetode Java menyediakan mekanisme untuk kode Java untuk memanggil kode asli OS, baik karena alasan fungsional atau kinerja.

Contoh:

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();

Dalam Runtime.classfile yang sesuai di OpenJDK, terletak di JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.class, berisi metode ini dan memberi tag mereka dengan ACC_NATIVE( 0x0100), dan metode ini tidak mengandung atribut Code , yang berarti metode ini tidak memiliki logika koding yang sebenarnya dalam Runtime.classfile:

  • Metode 13 availableProcessors: ditandai sebagai bawaan dan tanpa atribut Kode
  • Metode 14 freeMemory: ditandai sebagai bawaan dan tanpa atribut Kode
  • Metode 15 totalMemory: ditandai sebagai bawaan dan tanpa atribut Kode
  • Metode 16 maxMemory: ditandai sebagai bawaan dan tanpa atribut Kode
  • Metode 17 gc: ditandai sebagai bawaan dan tanpa atribut Kode

masukkan deskripsi gambar di sini

Logika pengkodean sebenarnya ada di file Runtime.c yang sesuai :

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  }

Dan Cpengkodean ini dikompilasi ke dalam file libjava.so(Linux) atau libjava.dll(Windows), yang terletak di JAVA_HOME/jmods/java.base.jmod/lib/libjava.so:

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Referensi

Senang
sumber