【Java基礎】-- native關鍵字是幹什麼用的?

[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

1.怎麼調用到native方法的呢?

上面說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

2. java調用自定義native方法步驟

在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方法,在編譯的時候都會自動去加載動態連接庫文件,而不須要咱們本身去操做了。

3.使用native的缺點

使用native的缺點:可移植性差,把對底層的控制權交給其餘語言,那麼也會出現不穩定性,慶幸的是如今操做系統的底層實現基本不會改變。上面hsahcode()的計算真是經過內存所在的內存塊來計算的,java是沒法直接操做內存的。

【做者簡介】
秦懷,公衆號【秦懷雜貨店】做者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。這個世界但願一切都很快,更快,可是我但願本身能走好每一步,寫好每一篇文章,期待和大家一塊兒交流。

此文章僅表明本身(本菜鳥)學習積累記錄,或者學習筆記,若有侵權,請聯繫做者覈實刪除。人無完人,文章也同樣,文筆稚嫩,在下不才,勿噴,若是有錯誤之處,還望指出,感激涕零~

相關文章
相關標籤/搜索