2011-05-23 97 views
360

在玩this puzzle(這是一個Java關鍵字瑣事遊戲)時,我碰到了native關鍵字。Java中的native關鍵字是什麼?

Java中使用的native關鍵字是什麼?

+10

另請參見[Java中的本機實現](http://stackoverflow.com/q/557574/122607),[本機在Java中的使用](http://stackoverflow.com/q/2902618/122607)和[本機關鍵字的作用是什麼?](http://stackoverflow.com/q/3598315/122607)。 – Pops 2011-05-23 18:53:17

回答

259

native關鍵字應用於指示該方法使用JNI(Java本機接口)以本機代碼實現的方法。

+127

Ignotum per ignotius :-) – MaxZoom 2015-09-11 22:17:32

+35

拉丁語爲「未知的未知」。保存搜索 – iantonuk 2017-05-16 06:59:39

+19

^此評論爲該術語的例證。 Ignotum per ignotius是當某人提供比它應該解釋的東西更難以理解的解釋時。 – AndrewF 2017-05-31 21:48:56

18

當SLak回答時,native關鍵字用於調用本地代碼。

它也被GWT用於實現javascript方法。

329

它標誌着一種方法,它將用其他語言而不是Java來實現。它與JNI(Java本地接口)一起工作。

過去使用本地方法來編寫性能關鍵部分,但隨着Java變得更快,現在不太常見。當需要本地方法時

  • 您需要從Java調用其他語言編寫的庫。

  • 您需要訪問只能從其他語言(通常爲C)訪問的系統或硬件資源。實際上,許多與真實計算機交互的系統函數(例如磁盤和網絡IO)只能這樣做,因爲它們調用本地代碼。

另請參見 Java Native Interface Specification

+3

這是我的理解我在java文件中編寫System.currentTimeMillis()(這是本地的)然後這個工作,JNI將調用庫或一些用C或C++或彙編語言編寫的函數,然後將一些值返回給我的java代碼。例如:這裏currentTimeMillis方法在JNI的幫助下調用一個本地代碼,並且本地代碼與系統資源ex通信:一個坐在主板上的計時器,從而獲得返回值(系統時間)。請糾正我? – MKod 2014-12-25 08:28:07

+3

像'currentTimeMillis'這樣的@MKod方法是JDK的一部分,它們使用'native'註釋,因爲實現在JDK源代碼本身。實現使用匯編語言的可能性很小;它可能會調用JVM正在運行的操作系統的API方法。例如,在Windows上,它可能會在kernel32.dll中調用DLL方法'GetSystemTime'。在另一個操作系統上它會有不同的實現。但是,當您使用'native'作爲您正在編寫的方法(而不是JDK方法)時,您必須使用JNI提供實現。 – Kidburla 2015-10-14 14:35:51

+0

此聲明對Native關鍵字非常重要......「您需要訪問只能從其他語言(通常爲C)可訪問的系統或硬件資源」。 – atiqkhaled 2017-02-26 15:55:25

52

直從the Java Language Specification

native在依賴於平臺的代碼實現的,典型地寫在其他編程語言如C,C++的方法, FORTRAN或彙編語言。方法native的主體僅以分號給出,表示實現被省略,而不是塊。

13

實現本機代碼的函數被聲明爲本機。

Java本機接口(JNI)是一種編程框架,能夠在Java虛擬機(JVM)打電話,並通過調用,本地應用程序(特定於硬件和操作系統的程序運行Java代碼平臺)和使用其他語言編寫的庫,如C,C++和彙編語言。

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

6

天然是在Java中的關鍵字,它用於使未實現結構(方法)等作爲抽象但它是一個依賴於平臺的,例如本機代碼,並從本地棧不是Java堆執行。

6

NATIVE是非訪問修飾符,它只能應用於METHOD。它指示方法或代碼的PLATFORM-DEPENDENT implimentation。

290

小例子使事情更清晰:

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合作。

Example on GitHub給你玩。

強調了必須在C函數名_1轉義Java包/文件名如提到:Invoking JNI functions in Android package name containing underscore

解讀

它允許你:

  • 通話編譯的動態加載庫(這裏用C語言編寫),並帶有Java
  • 的任意彙編代碼和得到的結果返回到Java的

這可以用於:

  • 寫上一個關鍵部分更快的代碼具有更好的CPU安裝說明(不是CPU便攜式)
  • 進行直接的系統調用(不OS便攜式)

與便攜性較低的權衡。

也可以爲你從C調用Java,但你必須先在C上創建一個JVM:How to call Java functions from C++?

的Android NDK

的概念是準確的在這方面是相同的,不同之處你必須使用Android樣板進行設置。

官方NDK庫包含 「規範」 的例子,如HELLO-JNI應用:

在你unzip.apk與NDK Android上的O,你可以看到對應於lib/arm64-v8a/libnative-lib.so下的本地代碼的預編譯的.so

TODO確認:此外,file /data/app/com.android.appname-*/oat/arm64/base.odex,說,這是一個共享庫,我認爲這是預編譯.DEX對應於ART的Java文件的AOT,還看到:What are ODEX files in Android?所以,也許在Java實際上也通過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 

這使我們hotspot/src/share/vm/prims/jvm.cpp#l580

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

擴大了一堆宏之後,我們來得出這是定義的結論。

+39

像你這樣的答案是我喜歡並持續使用StackOverflow的原因。如果您可以投票將答案與接受的答案進行合併,或者以某種方式將兩個答案標記爲已接受,那將會非常棒。 – 2015-11-10 05:13:29

+3

@JonnyHenly謝謝!合併會很有趣,但是由於我們已經投票贊成,所以很難派發代表,也許這並不重要。我們可能會看到有一天是:http://meta.stackexchange.com/questions/15805/how-can-we-make-good-answers-to-old-questions-float-to-the-top – 2015-11-10 06:59:07

+3

它是總是很高興看到具有詳細示例代碼的答案。 – 2016-04-10 07:07:12

4
  • native是java中的關鍵字,它表示依賴於平臺。
  • native方法充當Java(JNI)和其他編程語言之間的接口。
1

native關鍵字用於聲明在平臺相關代碼(如C或C++)中實現的方法。當一個方法被標記爲本地時,它不能有一個正文,而必須以分號結尾。 Java本地接口(JNI)規範管理實現本地方法的規則和準則,例如Java和本機應用程序之間的數據類型轉換。

下面的示例示出了一類具有聲明爲本地的方法:

public class NativeExample { 
    public native void fastCopyFile(String sourceFile, String destFile); 
} 
4

NATIVË關鍵字用於聲明其在依賴於平臺的代碼,如C或C++實現的方法。當一個方法被標記爲本地時,它不能有一個正文,而必須以分號結尾。 Java本地接口(JNI)規範管理實現本地方法的規則和準則,例如Java和本機應用程序之間的數據類型轉換。

下面的示例示出了具有一個方法的類聲明爲天然

public class NativeExample { 

public native void fastCopyFile(String sourceFile, String destFile); 

} 

的本地方法缺點:

  • 本地方法存儲與.DLL(動態鏈接庫)在Windows中的文件擴展名。 DLL文件是機器相關的。因此,本地方法是不可移植的。

  • 由於原生方法使用機器碼,因此會導致嚴重的安全問題。

1

native關鍵字被施加到一個方法,以表明該方法在本地代碼使用JNI(Java本地接口)實現。本地是適用於修改器只適用於方法,我們不能在其他地方應用。在C,C++中實現的方法稱爲本地方法或外部方法。

native關鍵字的主要目標是:

  • 爲了提高系統的性能。
  • 實現任務級別/內存級別的通信。
  • 使用已有的傳統非Java代碼。