Java native 關鍵字
今天在看Thread類,啟動執行緒用的 start()方法,該方法使執行緒開始執行,jvm 呼叫這個執行緒的run方法。(執行緒不能重複start),而 start()
方法中又呼叫了 native start0()
方法,該方法沒有實現體,其實現體是由非java語言在外面實現的,JVM將控制呼叫本地方法的所有細節。Object 類中也有很多 native 方法。
JNI
Java Native Interface (JNI)提供了若干的API實現了Java和其他語言的通訊(主要是 C&C++)。簡單地講,一個Native Method就是一個java呼叫非java程式碼的介面。有了本地方法,java程式可以做任何應用層次的任務。
使用Native Method 原因
有些層次的任務用java實現起來不容易,或者對程式的效率很在意時,如果要使用一些java語言本身沒有提供封裝的作業系統的特性時,那麼也需要使用本地方法。JVM支援著java語言本身和執行時庫,它是java程式賴以生存的平臺,它由一個直譯器(解釋位元組碼)和一些連線到原生程式碼的庫組成,甚至JVM的一些部分就是用C寫的。例如類 java.lang.Thread 的setPriority0()方法,這個本地方法是用 C 實現的,並被植入 JVM 內部,更多的情況是本地方法由外部的動態連結庫(external dynamic link library)提供,然後被JVM呼叫。
JVM如何呼叫 Native Method
當一個類第一次被使用到時,這個類的位元組碼會被載入到記憶體。在這個被載入的位元組碼的入口維持著一個該類所有方法描述符的 list,這些方法描述符包含這樣一些資訊:方法程式碼存於何處,它有哪些引數,方法的描述符(public之類)等等。
如果一個方法描述符內有 native,這個描述符塊將有一個指向該方法的實現的指標。這些實現在一些DLL檔案內,但是它們會被作業系統載入到java程式的地址空間。當一個帶有本地方法的類被載入時,其相關的DLL並未被載入,因此指向方法實現的指標並不會被設定。當本地方法被呼叫之前,這些DLL才會被載入,這是通過呼叫 java.system.loadLibrary()
實現的。
使用 native 關鍵字說明這個方法是原生函式,也就是這個方法是用 C/C++ 語言實現的,並且被編譯成了DLL,由java去呼叫。
簡單例子
可以將native方法比作Java程式同C程式的介面,其實現步驟:
1、在Java中宣告native()方法,然後編譯(javac);
2、用 javah 命令產生一個.h檔案;
3、寫一個 .c 檔案實現 native 匯出方法,其中需要包含第二步產生的.h檔案(注意其中又包含了 JDK 帶的 jni.h 檔案,該檔案在 $JAVA_HOME/include
目錄下);
4、將第三步的 .c 檔案編譯成動態連結庫檔案;
5、在 Java 中用 System.loadLibrary() 方法載入第四步產生的動態連結庫檔案,這個 native() 方法就可以在Java中被訪問了。
新建個 Java 檔案,內容如下。
public class HelloWorld{
public native void sayHello();
static{
System.loadLibrary("HelloWorld");
}
public static void main(String[] args){
new HelloWorld().sayHello();
}
}
按上面步驟執行命令
javac HelloWorld.java
javah HelloWorld
HelloWorld.h 檔案內容
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
寫個 .c 檔案實現 HelloWorld.h 檔案中的函式JNIEXPORT void JNICALL Java_HelloWorld_sayHello(JNIEnv *, jobject);
檔案內容如下。
#include "HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_sayHello(JNIEnv *env, jobject obj)
{
printf("Hello World!");
return;
}
生產動態連結庫:
Windows——.DLL;Linux——.so;Mac OS X——.dylib; .dylib是Mach-O格式,也就是Mac OS X下的二進位制檔案格式。Mac OS X提供了一系列工具,用於建立和訪問動態連結庫。
編譯器/usr/bin/cc,也就是gcc了,Apple改過的
彙編器/usr/bin/as
連結器/usr/bin/ld // 可以合併.o檔案 ld -r -o c.o a.o b.o
Mac 有個自己的工具,/usr/bin/libtool,來建立動態連結庫,這個libtool不是
GNU的那個同名的libtool。
//生成sayHello.o
cc -I"/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/include/" -I"/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/include/darwin" -c SayHello.c
libtool -dynamic -o sayHello.dylib sayHello.o
生成 .o 檔案時,-I 是為了能夠載入到 jni.h 和 jni_md.h 檔案,
發現我的 libtool 已經是gun工具的了,貌似不能用,於是就還是使用了 gcc 來生成動態連結庫
gcc -fPIC -I"/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/include/" -I"/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/include/darwin" -c HelloWorld.c
//生成動態連結庫
gcc -fPIC -dynamiclib HelloWorld.o -o HelloWorld.dylib
再執行 java 檔案就可以了。
訪問動態連結庫
nm a.dylib
可以看到匯出符號表等。
另一個Mac上的常用工具是 otool ,比如想看看c.dylib的依賴關係
otool -L a.dylib
相關文章
- Java native關鍵字Java
- java中native關鍵字的用法Java
- [java]transient關鍵字Java
- java中this關鍵字Java
- java transient關鍵字Java
- java之this關鍵字Java
- Java關鍵字(八)——synchronizedJavasynchronized
- Java 的 static 關鍵字Java
- JAVA中的關鍵字Java
- JAVA static關鍵字理解Java
- Java Final關鍵字Java
- java之static關鍵字Java
- java之super關鍵字Java
- synchronized關鍵字 - [JAVA心得]synchronizedJava
- [java基礎]之JAVA關鍵字Java
- Java™ 教程(使用super關鍵字)Java
- Java volatile關鍵字作用Java
- Java進階——super關鍵字Java
- Java 關鍵字之 finalJava
- Java中final關鍵字Java
- Java中this與super關鍵字Java
- Java volatile關鍵字解析Java
- java之final關鍵字Java
- java中this關鍵字的用法Java
- java中的static關鍵字Java
- Java併發--final關鍵字Java
- java基礎-關鍵字finalJava
- java中的instanceof關鍵字Java
- Java併發——關鍵字synchronized解析Javasynchronized
- Java中的各種關鍵字Java
- 在Java中this關鍵字的使用Java
- Java中transient關鍵字的作用Java
- java oop 修飾符&關鍵字JavaOOP
- java中static關鍵字的作用Java
- Java關鍵字volatile的理解Java
- Java中的static關鍵字解析Java
- Java transient關鍵字使用總結Java
- Java物件導向重要關鍵字Java物件