इस पहेली को खेलते हुए (यह एक जावा कीवर्ड ट्रिविया गेम है), मैं native
कीवर्ड भर में आया ।
जावा में मूल कीवर्ड किसके लिए उपयोग किया जाता है?
इस पहेली को खेलते हुए (यह एक जावा कीवर्ड ट्रिविया गेम है), मैं native
कीवर्ड भर में आया ।
जावा में मूल कीवर्ड किसके लिए उपयोग किया जाता है?
जवाबों:
यह native
संकेत देने के लिए कि यह विधि जेएनआई (जावा नेटिव इंटरफेस) का उपयोग करके मूल कोड में लागू की गई है, इस पद्धति के लिए कीवर्ड लागू किया जाता है।
न्यूनतम रननीय उदाहरण
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
सी फ़ंक्शन नाम के साथ बच जाना चाहिए जैसा कि उल्लेख किया गया है: एंड्रॉइड पैकेज नाम में जेएनआई कार्यों को शामिल करना अंडरस्कोर युक्त
व्याख्या
native
आपको अनुमति देता है:
यह करने के लिए इस्तेमाल किया जा सकता है:
कम पोर्टेबिलिटी के व्यापार के साथ।
आपके लिए जावा को C से कॉल करना भी संभव है, लेकिन आपको पहले C में JVM बनाना होगा: C ++ से जावा फ़ंक्शन को कैसे कॉल करें?
Android NDK
इस संदर्भ में अवधारणा बिल्कुल समान है, सिवाय इसके कि आपको इसे स्थापित करने के लिए एंड्रॉइड बॉयलरप्लेट का उपयोग करना होगा।
आधिकारिक NDK रिपॉजिटरी में हैलो-जानी ऐप जैसे "कैनोनिकल" उदाहरण शामिल हैं:
आप में unzip
एक .apk
NDK एंड्रॉयड हे पर के साथ, आप पहले से संकलित देख सकते हैं .so
के तहत मूल कोड से मेल खाती है कि lib/arm64-v8a/libnative-lib.so
।
TODO पुष्टि करता है: इसके अलावा, file /data/app/com.android.appname-*/oat/arm64/base.odex
कहते हैं कि यह एक साझा पुस्तकालय है, जो मुझे लगता है कि एओटी पहले से तैयार है। एआरटी में जावा फ़ाइलों के अनुरूप है, यह भी देखें: एंड्रॉइड में ओडीएक्स फाइलें क्या हैं? तो शायद जावा वास्तव में एक native
इंटरफ़ेस के माध्यम से भी चलाया जाता है ?
OpenJDK 8 में उदाहरण
आइए पाते हैं कि Object#clone
jdk8u60-b27 में कहां परिभाषित किया गया है।
हम यह निष्कर्ष निकालेंगे कि यह एक native
कॉल के साथ लागू किया गया है ।
पहले हम पाते हैं:
find . -name Object.java
जो हमें jdk / src / share / classes / java / lang / object.java # l212 पर ले जाता है :
protected native Object clone() throws CloneNotSupportedException;
अब कठिन हिस्सा आता है, जहां यह पता चलता है कि क्लोन सभी अप्रत्यक्ष के बीच है। क्वेरी से मुझे मदद मिली:
find . -iname object.c
जो या तो C या C ++ फ़ाइलों को खोजेगा जो ऑब्जेक्ट के मूल तरीकों को लागू कर सकते हैं। यह हमें 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
जावा विधि के लिए, C ++ फ़ंक्शन का दूसरा पैरामीटर टाइप jclass
और नहीं है jobject
।
यह एक विधि को चिह्नित करता है, जिसे यह जावा में नहीं, अन्य भाषाओं में लागू किया जाएगा। यह जेएनआई (जावा नेटिव इंटरफेस) के साथ मिलकर काम करता है।
प्रदर्शन महत्वपूर्ण वर्गों को लिखने के लिए अतीत में मूल तरीकों का इस्तेमाल किया गया था लेकिन जावा के तेज होने के साथ यह अब कम आम है। वर्तमान में मूल तरीकों की जरूरत है जब
आपको जावा से एक पुस्तकालय कॉल करने की आवश्यकता है जो अन्य भाषा में लिखा गया है।
आपको सिस्टम या हार्डवेयर संसाधनों तक पहुंचने की आवश्यकता है जो केवल दूसरी भाषा (आमतौर पर सी) से उपलब्ध हैं। दरअसल, कई सिस्टम फ़ंक्शंस जो वास्तविक कंप्यूटर (डिस्क और नेटवर्क IO, उदाहरण के लिए) के साथ बातचीत करते हैं, केवल इसलिए ऐसा कर सकते हैं क्योंकि वे मूल कोड कहते हैं।
इसके अलावा जावा नेटिव इंटरफेस स्पेसिफिकेशन देखें
currentTimeMillis
JDK का हिस्सा हैं और इन्हें एनोटेट किया जाता है native
क्योंकि कार्यान्वयन JDK स्रोत कोड में ही होता है। यह बहुत संभावना नहीं है कि कार्यान्वयन विधानसभा भाषा का उपयोग करता है; यह शायद ऑपरेटिंग सिस्टम का एक एपीआई तरीका कहता है जो JVM शीर्ष पर चल रहा है। उदाहरण के लिए विंडोज पर यह GetSystemTime
कर्नेल 32.dll में DLL विधि कह सकता है । दूसरे OS पर इसका अलग कार्यान्वयन होगा। हालाँकि जब आप native
एक विधि के लिए उपयोग करते हैं जो आप लिख रहे हैं (एक JDK विधि के विपरीत) तो आपको JNI का उपयोग करके कार्यान्वयन प्रदान करना होगा।
currentTimeMillis
मूल के रूप में चिह्नित है, java.lang.System
इसलिए यह जेएनआई का उपयोग करता है, क्या यह सही नहीं है?
से सीधे जावा भाषा विशिष्टता :
एक विधि जिसे
native
प्लेटफ़ॉर्म-डिपेंडेंट कोड में लागू किया जाता है, आमतौर पर C, C ++, FORTRAN, या असेंबली भाषा जैसी किसी अन्य प्रोग्रामिंग भाषा में लिखी जाती है। एकnative
विधि का शरीर केवल एक अर्धविराम के रूप में दिया जाता है, यह दर्शाता है कि कार्यान्वयन एक ब्लॉक के बजाय, छोड़ा गया है।
मूल कोड को लागू करने वाले कार्यों को मूल घोषित किया जाता है।
जावा नेटिव इंटरफ़ेस (JNI) एक प्रोग्रामिंग फ्रेमवर्क है जो जावा कोड को जावा वर्चुअल मशीन (JVM) में कॉल करने के लिए, और देशी अनुप्रयोगों (हार्डवेयर और ऑपरेटिंग सिस्टम प्लेटफॉर्म के लिए विशिष्ट प्रोग्राम) और पुस्तकालयों में लिखे जाने के लिए सक्षम बनाता है। अन्य भाषाएँ जैसे C, C ++ और असेंबली।
नेटिव जावा में एक कीवर्ड है, जिसका उपयोग अमूर्त की तरह अनइम्प्लीमेंटेड स्ट्रक्चर (विधि) बनाने के लिए किया जाता है, लेकिन यह एक प्लेटफॉर्म होगा जो कि देशी कोड पर निर्भर होता है और नेटिव स्टैक से जावा स्टैक से निष्पादित होता है।
जावा native
विधि जावा कोड के लिए ओएस देशी कोड को कॉल करने के लिए एक तंत्र प्रदान करती है, या तो कार्यात्मक या प्रदर्शन कारणों के कारण।
उदाहरण:
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
: मूल और कोई कोड विशेषता के रूप में टैग की गईfreeMemory
: मूल और कोई कोड विशेषता के रूप में टैग की गई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
(लिनक्स) या libjava.dll
(विंडोज) फ़ाइल में संकलित किया गया है JAVA_HOME/jmods/java.base.jmod/lib/libjava.so
:
संदर्भ