ในขณะที่เล่นปริศนานี้ (เป็นเกมเรื่องไม่สำคัญของ 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
.so
lib/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
:
การอ้างอิง