ในขณะที่เล่นปริศนานี้ (เป็นเกมเรื่องไม่สำคัญของ Java) ฉันเจอnativeคำค้นหานั้นแล้ว
คำหลักดั้งเดิมใน Java ใช้ทำอะไร
ในขณะที่เล่นปริศนานี้ (เป็นเกมเรื่องไม่สำคัญของ Java) ฉันเจอnativeคำค้นหานั้นแล้ว
คำหลักดั้งเดิมใน Java ใช้ทำอะไร
คำตอบ:
nativeคำหลักที่ถูกนำไปใช้วิธีการที่จะแสดงให้เห็นว่าวิธีการที่จะดำเนินการในรหัสพื้นเมืองโดยใช้ JNI (Java อินเตอร์เฟสพื้นเมือง)
ตัวอย่างที่เรียกใช้น้อยที่สุด
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;
}
รวบรวมและเรียกใช้:
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
เอาท์พุท:
4
ทดสอบบน Ubuntu 14.04 AMD64 ยังทำงานร่วมกับ Oracle JDK 1.8.0_45
ตัวอย่างบน GitHubเพื่อให้คุณเล่นด้วย
ขีด_1ล่างในชื่อแพคเกจ / ไฟล์ Java จะต้องหลีกเลี่ยงในชื่อฟังก์ชั่น C ตามที่กล่าวไว้ที่: เรียกใช้ฟังก์ชั่น JNI ในชื่อแพคเกจ Android ที่มีขีดล่าง
การตีความ
native ช่วยให้คุณ:
สิ่งนี้สามารถใช้เพื่อ:
กับการแลกเปลี่ยนของการพกพาที่ต่ำกว่า
เป็นไปได้สำหรับคุณที่จะเรียก Java จาก C แต่คุณต้องสร้าง JVM ใน C: วิธีการเรียกฟังก์ชั่น Java จาก C ++?
คล้าย APIs ขยายพื้นเมืองนอกจากนี้ยังมีคนอื่น ๆ ใน "ภาษา VM" หลายคนด้วยเหตุผลเดียวกันเช่นงูหลาม , Node.js , ทับทิม
Android NDK
แนวคิดนี้เหมือนกันทุกประการในบริบทนี้ยกเว้นว่าคุณต้องใช้แผ่นฐานข้อมูล Android เพื่อตั้งค่า
ที่เก็บ NDK อย่างเป็นทางการมีตัวอย่าง "canonical" เช่นแอป hello-jni:
ในตัวคุณกับ NDK บน Android O, คุณสามารถเห็นก่อนรวบรวมที่สอดคล้องกับรหัสพื้นเมืองภายใต้unzip.apk.solib/arm64-v8a/libnative-lib.so
TODO confirm: ยิ่งไปกว่านั้นfile /data/app/com.android.appname-*/oat/arm64/base.odexบอกว่ามันเป็น shared library ซึ่งฉันคิดว่าเป็น AOT ที่คอมไพล์แล้ว. dex ที่สอดคล้องกับไฟล์ Java ใน ART ดูที่: ไฟล์ ODEX ใน Android คืออะไร? ดังนั้นบางที Java อาจทำงานผ่านnativeอินเตอร์เฟซจริงหรือ
ตัวอย่างใน OpenJDK 8
มาหา find ที่Object#cloneกำหนดไว้ใน jdk8u60-b27
เราจะสรุปได้ว่ามันจะดำเนินการกับnativeสาย
ก่อนอื่นเราพบว่า:
find . -name Object.java
ซึ่งนำเราไปสู่jdk / src / share / คลาส / java / lang / Object.java # l212 :
protected native Object clone() throws CloneNotSupportedException;
ตอนนี้ส่วนที่ยากมาหาที่โคลนอยู่ท่ามกลางทุกทิศทาง แบบสอบถามที่ช่วยฉันคือ:
find . -iname object.c
ซึ่งจะค้นหาไฟล์ C หรือ C ++ ที่อาจใช้วิธีเนทีฟของ Object มันนำเราไปสู่jdk / share / native / 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]));
}
ซึ่งนำเราไปสู่JVM_Cloneสัญลักษณ์:
grep -R JVM_Clone
ซึ่งนำเราไปสู่ฮอตสปอต / src / share / vm / prims / jvm.cpp # l580 :
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
หลังจากขยายมาโครเป็นจำนวนมากเราก็มาถึงข้อสรุปว่านี่คือจุดนิยาม
static nativeวิธี Java, พารามิเตอร์ที่สองของฟังก์ชัน c ++ เป็นประเภทและไม่ได้jclass jobject
มันทำเครื่องหมายวิธีที่มันจะถูกนำมาใช้ในภาษาอื่น ๆ ไม่ได้อยู่ใน Java มันทำงานร่วมกับ JNI (Java Native Interface)
วิธีการแบบเนทีฟถูกใช้ในอดีตเพื่อเขียนส่วนที่สำคัญต่อประสิทธิภาพ แต่ด้วย Java ที่ได้รับเร็วขึ้น วิธีการเนทีฟเป็นสิ่งจำเป็นในปัจจุบันเมื่อ
คุณต้องเรียกไลบรารีจาก Java ที่เขียนด้วยภาษาอื่น
คุณต้องเข้าถึงระบบหรือทรัพยากรฮาร์ดแวร์ที่สามารถเข้าถึงได้จากภาษาอื่นเท่านั้น (โดยทั่วไปคือ C) ที่จริงแล้วฟังก์ชั่นระบบจำนวนมากที่ทำงานกับคอมพิวเตอร์จริง (เช่นดิสก์และเครือข่าย IO เป็นต้น) ทำได้เพียงเพราะพวกเขาเรียกใช้เนทีฟโค้ด
ดูเพิ่มเติม ข้อมูลจำเพาะ Java Native Interface
currentTimeMillisเป็นส่วนหนึ่งของ JDK และพวกเขามีข้อเขียนด้วยnativeเพราะการดำเนินการอยู่ในซอร์สโค้ด JDK ตัวเอง ไม่น่าเป็นไปได้มากที่การใช้งานจะใช้ภาษาแอสเซมบลี มันอาจเรียกวิธีการ API ของระบบปฏิบัติการที่ JVM ทำงานอยู่ด้านบน ตัวอย่างเช่นบน Windows อาจเรียกใช้วิธี DLL GetSystemTimeใน kernel32.dll ในระบบปฏิบัติการอื่นมันจะมีการใช้งานที่แตกต่างกัน อย่างไรก็ตามเมื่อคุณใช้nativeสำหรับวิธีการที่คุณเขียน (ซึ่งตรงข้ามกับวิธี JDK) คุณจะต้องให้การใช้งานโดยใช้ JNI
currentTimeMillisถูกทำเครื่องหมายว่าเป็นภาษาพื้นเมืองjava.lang.Systemดังนั้นจึงใช้ JNI ใช่ไหม
ตรงจากข้อมูลจำเพาะ Java Language :
วิธีการที่
nativeนำมาใช้ในรหัสขึ้นอยู่กับแพลตฟอร์มโดยทั่วไปจะเขียนในภาษาการเขียนโปรแกรมอื่นเช่น C, C ++, FORTRAN หรือภาษาแอสเซมบลี เนื้อความของnativeเมธอดถูกกำหนดเป็นเซมิโคลอนเท่านั้นซึ่งบ่งชี้ว่าละเว้นการใช้งานแทนบล็อก
ตามที่ SLaks ตอบแล้วnativeคำสำคัญสำหรับการเรียกรหัสเนทีฟ
มันยังใช้โดยGWTสำหรับการใช้วิธีจาวาสคริปต์
ฟังก์ชั่นที่ใช้รหัสเนทีฟจะถูกประกาศเนทีฟ
Java Native Interface (JNI) เป็นกรอบการเขียนโปรแกรมที่เปิดใช้งานโค้ด Java ที่ทำงานใน Java Virtual Machine (JVM) ในการโทรและจะถูกเรียกโดยแอพพลิเคชั่นดั้งเดิม (โปรแกรมเฉพาะกับฮาร์ดแวร์และระบบปฏิบัติการแพลตฟอร์ม) และห้องสมุดที่เขียนด้วยภาษา ภาษาอื่นเช่น C, C ++ และชุดประกอบ
NATIVE เป็นตัวแก้ไขการเข้าถึงที่ไม่สามารถใช้ได้กับวิธีการเท่านั้น มันแสดงให้เห็นถึงการใช้งานวิธีการหรือรหัส PLATFORM - ขึ้นอยู่กับ
native คือคีย์เวิร์ดใน java ซึ่งใช้ในการสร้างโครงสร้าง unimplemented (method) เหมือนเป็นนามธรรม แต่มันจะขึ้นอยู่กับแพลตฟอร์มเช่นโค้ดเนมและรันจาก native stack ไม่ใช่ java stack
native เป็นคำหลักใน java มันบ่งชี้ว่าขึ้นอยู่กับแพลตฟอร์มnativeเมธอดจะทำหน้าที่เป็นอินเตอร์เฟสระหว่าง Java ( JNI ) และภาษาการเขียนโปรแกรมอื่น ๆชวา nativeเมธอดจัดเตรียมกลไกสำหรับโค้ด Java เพื่อเรียกใช้โค้ดเนทีฟระบบปฏิบัติการเนื่องจากเหตุผลด้านการใช้งานหรือประสิทธิภาพ
ตัวอย่าง:
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();
ในRuntime.classไฟล์ที่เกี่ยวข้องใน OpenJDK อยู่ในJAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.classนั้นมีวิธีการเหล่านี้และติดแท็กพวกเขาด้วยACC_NATIVE( 0x0100) และวิธีการเหล่านี้ไม่มีแอตทริบิวต์รหัสซึ่งหมายความว่าวิธีเหล่านี้ไม่มีตรรกะการเข้ารหัสที่แท้จริงในRuntime.classไฟล์:
availableProcessors : แท็กเป็น native และไม่มี Code attributefreeMemory : แท็กเป็นดั้งเดิมและไม่มีแอตทริบิวต์ของรหัสtotalMemory : แท็กเป็นดั้งเดิมและไม่มีแอตทริบิวต์ของรหัสmaxMemory : แท็กเป็นดั้งเดิมและไม่มีแอตทริบิวต์ของรหัสgc: แท็กเป็นเนทิฟและไม่มีรหัสคุณลักษณะตรรกะการเข้ารหัสในความเป็นจริงอยู่ในไฟล์Runtime.c ที่สอดคล้องกัน:
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 }
และCการเข้ารหัสเหล่านี้จะถูกรวบรวมเป็นไฟล์libjava.so(Linux) หรือlibjava.dll(Windows) ซึ่งอยู่ที่JAVA_HOME/jmods/java.base.jmod/lib/libjava.so:
การอ้างอิง