以java中java.lang.System類中的一個得到系統當前時間的native方法為例,對native關鍵字進行說明:
__________________________________________________________
public final class System {//final關鍵字修飾的類不能被繼承
.......
/**
*返回系統當前時間(該方法依賴於底層操作系統的實現)
*/
public static native long currentTimeMillis();
.......
}
__________________________________________________________
對於上面的currentTimeMillis();聲明為native 表明:該方法的具體實現是依賴於底層的操作系統平台,並非java語言實現。
所以,一個native方法就是java調用非java代碼的接口,當在方法中調用一些不是由java語言寫的代碼或者在方法中用java語言
直接操縱計算機硬件時要聲明為native方法。native 方法中除了不能和abstract關鍵字連用(abstract表示方法是空實現,這顯然與native調用外部實現的事實不符),非native方法並無區別。
---
JAVA本地方法適用的情況
1.為了使用底層的主機平台的某個特性,而這個特性不能通過JAVA API訪問
2.為了訪問一個老的系統或者使用一個已有的庫,而這個系統或這個庫不是用JAVA編寫的
3.為了加快程序的性能,而將一段時間敏感的代碼作為本地方法實現。
----------------------------------------
類首次被使用到時,編譯生成字節碼會被加載到內存。在該字節碼的入口維持着一個該類所有方法描述符的列表,這些方法描述符包含了類的詳細信息。對應native方法,描述符塊中會有一個指向該方法的實現的指針。這些實現在一些DLL文件(動態鏈接庫文件dll是由java類編譯后的.h文件及jni.h文件信息和具體的方法實現等編譯生成的)內,當native方法被調用時,java會調用System.loadLibrary(*.dll)方法加載該dll。
其中,java通過javah(Javah:產生可以調用Java過程的C過程,或建立能被Java程序調用的C過程的頭文件)生成該類的.h文件。
jni(Java Native Interface,java本地接口)
------------------------------------------下面是加載dll文件的具體實現-------
Java代碼
/**
*java.lang.System中, 加載由 libname 參數指定的系統庫
*/
public static void loadLibrary(String libname) {//調用Runtime的loadLibrary方法
Runtime.getRuntime().loadLibrary0(getCallerClass(), libname);
}
/**
*Runtime的loadLibrary方法(帶有synchronized的同步方法)
*/
synchronized void loadLibrary0(Class fromClass, String libname) {
//用於判斷libname所指定文件的合法性
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkLink(libname);
}
if (libname.indexOf((int)File.separatorChar) != -1) {
throw new UnsatisfiedLinkError(
"Directory separator should not appear in library name: " + libname);
}
//調用ClassLoader的loadLibrary方法
ClassLoader.loadLibrary(fromClass, libname, false);
}
/**
*ClassLoader的loadLibrary方法
*/
// Invoked in the java.lang.Runtime class to implement load and loadLibrary.
static void loadLibrary(Class fromClass, String name,boolean isAbsolute) {
try {
if (!DownloadManager.isJREComplete() &&
!DownloadManager.isCurrentThreadDownloading()) {
DownloadManager.downloadFile("bin/" + System.mapLibraryName(name));
}
} catch (Exception e) {
throw new UnsatisfiedLinkError("Error downloading library "
+ name + ": " + e);
}
ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader();
if (sys_paths == null) {
usr_paths = initializePath("java.library.path");
sys_paths = initializePath("sun.boot.library.path");
}
}
.......
}
/**
*java.lang.System中, 加載由 libname 參數指定的系統庫
*/
public static void loadLibrary(String libname) {//調用Runtime的loadLibrary方法
Runtime.getRuntime().loadLibrary0(getCallerClass(), libname);
}
/**
*Runtime的loadLibrary方法(帶有synchronized的同步方法)
*/
synchronized void loadLibrary0(Class fromClass, String libname) {
//用於判斷libname所指定文件的合法性
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkLink(libname);
}
if (libname.indexOf((int)File.separatorChar) != -1) {
throw new UnsatisfiedLinkError(
"Directory separator should not appear in library name: " + libname);
}
//調用ClassLoader的loadLibrary方法
ClassLoader.loadLibrary(fromClass, libname, false);
}
/**
*ClassLoader的loadLibrary方法
*/
// Invoked in the java.lang.Runtime class to implement load and loadLibrary.
static void loadLibrary(Class fromClass, String name, boolean isAbsolute) {
try {
if (!DownloadManager.isJREComplete() &&
!DownloadManager.isCurrentThreadDownloading()) {
DownloadManager.downloadFile("bin/" + System.mapLibraryName(name));
}
} catch (Exception e) {
throw new UnsatisfiedLinkError("Error downloading library "
+ name + ": " + e);
}
ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader();
if (sys_paths == null) {
usr_paths = initializePath("java.library.path");
sys_paths = initializePath("sun.boot.library.path");
}
}
.......
}--------------------------------------------------------------------------------------------------------------------------------
另外,java.lang.System還用到了java中的另外兩個比較常見的關鍵字:final和static。
在這里也做簡單的說明:
關於final:
final修飾的類(比如System)表示該類不可被繼承,所以final不能修飾interface或abstract類;
final修飾的方法不能被子類覆蓋(不能被Override),不能修飾構造函數;
final修飾字段屬性、參數時表示其被第一次賦值后不能被修改(但這里請注意,如果是一個對象,
不能修改的是該對象的引用,但是對象的內容還是可以修改的)
使用final的 好處:
1.防止被修改;2.final類型的方法被調用時,編譯器會把它嵌入進來在一定程度上會提高了編譯效率(注意是:一定程度,原因如下)。
編譯器有一種被稱為inline的機制,它會使你在調用final方法時,直接將方法主體插入到調用處,而不是進行例行的方法調用,例如保存斷點,壓棧等,這樣可能會使你的程序效率有所提高,然而當你的方法主體非常龐大時,或你在多處調用此方法,那么你的調用主體代碼便會迅速膨脹,可能反而會影響效率,所以你要慎用final進行方法定義。
---------
關於static:
static 可以理解為“類”級別的關鍵字,因此對於static不存在this的概念,當類被jvm加載時,會按照聲明的先后對static成員字段進行初始化
於是,static 可用於定義全局變量,而 static final 就可以定義一個常量