[TOC]
今天一不當心跟進Object的源碼中,發現一個native
關鍵字,一臉矇蔽,怎麼我歷來沒有用過。java
// 這是計算對象的hsahcode的方法,涉及到內存地址 public native int hashCode();
1.彙編生c
,c
生萬物,其實java要實現對底層的控制,仍是須要c/c++
幫忙,老大畢竟是老大。c++
2.native
關鍵字咱們開發應用的時候是用不到的,那何時用到呢?那些開發java語言的時候用到,native
關鍵字是與c++
聯合開發的時候使用的,要不java控制不了底層啊,好比內存。因此仍是那句:彙編生c
,c
生萬物,c++
是c
的升級版。shell
3.這是java
調用其餘地方的接口的一個聲明關鍵字,意思是這個方法不是java實現的,有挺多的編程語言都有這樣的特性,好比c++
裏面使用extern "c"
來表示告訴c++編譯器去調用c裏面已經實現好的函數,而不是本身去實現。native
方法有點像java
裏面的interface
,都不用去實現,而是有別人去實現,可是interface
是誰實現接口誰實現,native
方法是直接交給c/c++
來實現。java
只能調用,由操做系統實現。編程
4.native
方法不能與abstract
方法一塊兒使用,由於native
表示這些方法是有實現體的,可是abstract
卻表示這些方法是沒有實現體的,那麼二者矛盾,確定也不能一塊兒使用。windows
上面說native
表示這個方法不是java
實現的,那麼就不是原生態方法,也就不會存在這個文件中,而是存在其餘地方,那麼java要怎麼調用才能調用到呢?編程語言
- JNI(Java Native Interface)這是一個本機編程的接口,它也是java jdk(開發工具包)的一部分,JNI能夠支持java中使用其餘語言,java要調用其餘語言的接口,須要通過他處理。java所謂的跨平臺,在必定程度上放棄了底層操做,由於不一樣的硬件或者操做系統底層的操做都是不同的。
那麼咱們如今來寫一個程序:helloWorld.java
(個人全部寫的文件都放在桌面,同個文件夾便可)函數
public class helloworld{ static { System.loadLibrary("cSayHello"); } public static native void hello(); @SuppressWarnings("static-access") public static void main(String[] args){ new helloworld().hello(); } }
直接在編譯器運行這段代碼會出現下面錯誤:工具
上面的錯誤是說找不到cSayHello
:no cSayHello in java.library.path
,因此啊,這個c/c++
的方法咱們要本身實現,畢竟咱們用的不是操做系統以及定義好的方法。
因此咱們先來,使用cmd 在helloworld.java所在的目錄下 使用命令行:學習
javac helloworld javah helloworld
而後咱們能夠看到在helloworld.java所在的目錄下多了兩個文件,一個是helloworld.class文件,一個是helloworld.h文件。開發工具
打開helloworld.h,裏面引用了jni.h這個文件,這個文件在咱們安裝的java
目錄下面的include
文件下:
/* 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: hello * Signature: ()V */ JNIEXPORT void JNICALL Java_helloworld_hello (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
個人java
是裝在D盤
下面:
咱們來寫須要引入的c
文件cSayHello
,我也是放在桌面,反正同一個文件夾就能夠。
#include "helloworld.h" #include <stdio.h> JNIEXPORT void JNICALL Java_helloworld_hello(JNIEnv *env, jclass jc) { printf("java helloworld"); }
在windows
系統上,須要下載安裝WinGW Gcc
,安裝教程參考https://www.jianshu.com/p/535... 安裝成功cmd
輸入:
gcc -m64 -Wl,--add-stdcall-alias -I"D:\Java\jdk1.8.0_111\include" -I"D:\Java\jdk1.8.0_111\include\win32" -shared -o cSayHello.dll helloworld.c
而後直接運行,就能夠看到輸出了
java helloworld
在java中使用native的步驟:
1.在java代碼中聲明native方法
2.執行javah來生成一個.h文件
3.寫.cpp文件來實現native導出的方法,須要包含上面第二步產生的.h文件,同時也包含了jdk自帶的jni.h
4.將第三步的.cpp文件經過gcc 編譯成動態連接庫文件
5.在java中使用的用System.loadLibrary()方法加載第四步產生的動態連接庫文件,這個native()方法就能夠在Java中被訪問
通常狀況下,咱們jdk中聲明的native方法,在編譯的時候都會自動去加載動態連接庫文件,而不須要咱們本身去操做了。
使用native的缺點:可移植性差,把對底層的控制權交給其餘語言,那麼也會出現不穩定性,慶幸的是如今操做系統的底層實現基本不會改變。上面hsahcode()的計算真是經過內存所在的內存塊來計算的,java是沒法直接操做內存的。
【做者簡介】:
秦懷,公衆號【秦懷雜貨店】做者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。這個世界但願一切都很快,更快,可是我但願本身能走好每一步,寫好每一篇文章,期待和大家一塊兒交流。
此文章僅表明本身(本菜鳥)學習積累記錄,或者學習筆記,若有侵權,請聯繫做者覈實刪除。人無完人,文章也同樣,文筆稚嫩,在下不才,勿噴,若是有錯誤之處,還望指出,感激涕零~