Saat memainkan puzzle ini (Ini adalah game trivia kata kunci Java), saya menemukan native
kata kunci.
Untuk apa kata kunci asli di Jawa digunakan?
Saat memainkan puzzle ini (Ini adalah game trivia kata kunci Java), saya menemukan native
kata kunci.
Untuk apa kata kunci asli di Jawa digunakan?
Jawaban:
Kata native
kunci diterapkan pada metode untuk menunjukkan bahwa metode ini diterapkan dalam kode asli menggunakan JNI (Java Native Interface).
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 _1
dalam nama fungsi C seperti yang disebutkan di: Memanggil fungsi JNI dalam nama paket Android yang berisi garis bawah
Penafsiran
native
memungkinkan Anda untuk:
Ini dapat digunakan untuk:
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 unzip
seorang .apk
dengan NDK di Android O, Anda dapat melihat pre-compiled .so
yang 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.odex
mengatakan 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 native
antarmuka?
Contoh di OpenJDK 8
Mari kita temukan cari di mana Object#clone
didefinisikan dalam jdk8u60-b27.
Kami akan menyimpulkan bahwa itu dilaksanakan dengan native
panggilan.
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_Clone
simbol:
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.
static
native
metode Java, parameter kedua dari fungsi C ++ adalah tipe jclass
dan bukan jobject
.
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
currentTimeMillis
adalah bagian dari JDK dan mereka dijelaskan dengan native
karena 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 GetSystemTime
di kernel32.dll. Pada OS lain itu akan memiliki implementasi yang berbeda. Namun ketika Anda menggunakan native
untuk metode yang Anda tulis (sebagai lawan dari metode JDK) Anda harus menyediakan implementasi menggunakan JNI.
currentTimeMillis
ditandai sebagai asli java.lang.System
sehingga menggunakan JNI, bukankah begitu?
Langsung dari para Jawa Bahasa Spesifikasi :
Metode yang
native
diimplementasikan dalam kode yang tergantung pada platform, biasanya ditulis dalam bahasa pemrograman lain seperti C, C ++, FORTRAN, atau bahasa assembly. Badannative
metode diberikan sebagai titik koma saja, menunjukkan bahwa implementasi dihilangkan, bukan blok.
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.
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.
native
Metode 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.class
file 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.class
file:
availableProcessors
: ditandai sebagai bawaan dan tanpa atribut KodefreeMemory
: ditandai sebagai bawaan dan tanpa atribut KodetotalMemory
: ditandai sebagai bawaan dan tanpa atribut KodemaxMemory
: ditandai sebagai bawaan dan tanpa atribut Kodegc
: ditandai sebagai bawaan dan tanpa atribut KodeLogika 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 C
pengkodean ini dikompilasi ke dalam file libjava.so
(Linux) atau libjava.dll
(Windows), yang terletak di JAVA_HOME/jmods/java.base.jmod/lib/libjava.so
:
Referensi