程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java調用固有方法

java調用固有方法

編輯:關於JAVA

我們先從一個簡單的例子開始:一個Java程序調用固有方法,後者再調用Win32的API函數MessageBox(),顯示出一個圖形化的文本框。這個例子稍後也會與J/Direct一志使用。若您的平台不是Win32,只需將包含了下述內容的C頭:
#include <windows.h>
替換成:
#include <stdio.h>
並將對MessageBox()的調用換成調用printf()即可。
第一步是寫出對固有方法及它的自變量進行聲明的Java代碼:
 

class ShowMsgBox {
  public static void main(String [] args) {
    ShowMsgBox app = new ShowMsgBox();
    app.ShowMessage("Generated with JNI");
  }
  private native void ShowMessage(String msg);
  static {
    System.loadLibrary("MsgImpl");
  }
}

在固有方法聲明的後面,跟隨有一個static代碼塊,它會調用System.loadLibrary()(可在任何時候調用它,但這樣做更恰當)System.loadLibrary()將一個DLL載入內存,並建立同它的鏈接。DLL必須位於您的系統路徑,或者在包含了Java類文件的目錄中。根據具體的平台,JVM會自動添加適當的文件擴展名。

1. C頭文件生成器:javah
現在編譯您的Java源文件,並對編譯出來的.class文件運行javah。javah是在1.0版裡提供的,但由於我們要使用Java 1.1 JNI,所以必須指定-jni參數:
javah -jni ShowMsgBox
javah會讀入類文件,並為每個固有方法聲明在C或C++頭文件裡生成一個函數原型。下面是輸出結果——ShowMsgBox.h源文件(為符合本書的要求,稍微進行了一下修改):
 

/* DO NOT EDIT THIS FILE 
   - it is machine generated */
#include <jni.h>
/* Header for class ShowMsgBox */

#ifndef _Included_ShowMsgBox
#define _Included_ShowMsgBox
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     ShowMsgBox
 * Method:    ShowMessage
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL 
Java_ShowMsgBox_ShowMessage
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

從“#ifdef_cplusplus”這個預處理引導命令可以看出,該文件既可由C編譯器編譯,亦可由C++編譯器編譯。第一個#include命令包括jni.h——一個頭文件,作用之一是定義在文件其余部分用到的類型;JNIEXPORT和JNICALL是一些宏,它們進行了適當的擴充,以便與那些不同平台專用的引導命令配合;JNIEnv,jobject以及jstring則是JNI數據類型定義。

2. 名稱管理和函數簽名
JNI統一了固有方法的命名規則;這一點是非常重要的,因為它屬於虛擬機將Java調用與固有方法鏈接起來的機制的一部分。從根本上說,所有固有方法都要以一個“Java”起頭,後面跟隨Java方法的名字;下劃線字符則作為分隔符使用。若Java固有方法“過載”(即命名重復),那麼也把函數簽名追加到名字後面。在原型前面的注釋裡,大家可看到固有的簽名。欲了解命名規則和固有方法簽名更詳細的情況,請參考相應的JNI文檔。

3. 實現自己的DLL
此時,我們要做的全部事情就是寫一個C或C++源文件,在其中包含由javah生成的頭文件;並實現固有方法;然後編譯它,生成一個動態鏈接庫。這一部分的工作是與平台有關的,所以我假定讀者已經知道如何創建一個DLL。通過調用一個Win32 API,下面的代碼實現了固有方法。隨後,它會編譯和鏈接到一個名為MsgImpl.dll的文件裡:
 

#include <windows.h>
#include "ShowMsgBox.h"

BOOL APIENTRY DllMain(HANDLE hModule, 
  DWORD dwReason, void** lpReserved) {
  return TRUE;
}

JNIEXPORT void JNICALL 
Java_ShowMsgBox_ShowMessage(JNIEnv * jEnv, 
  jobject this, jstring jMsg) {
  const char * msg;
  msg = (*jEnv)->GetStringUTFChars(jEnv, jMsg,0);
  MessageBox(HWND_DESKTOP, msg, 
    "Thinking in Java: JNI",
    MB_OK | MB_ICONEXCLAMATION);
  (*jEnv)->ReleaseStringUTFChars(jEnv, jMsg,msg);
}

若對Win32沒有興趣,只需跳過MessageBox()調用;最有趣的部分是它周圍的代碼。傳遞到固有方法內部的自變量是返回Java的大門。第一個自變量是類型JNIEnv的,其中包含了回調JVM需要的所有掛鉤(下一節再詳細講述)。由於方法的類型不同,第二個自變量也有自己不同的含義。對於象上例那樣的非static方法(也叫作實例方法),第二個自變量等價於C++的“this”指針,並類似於Java的“this”:都引用了調用固有方法的那個對象。對於static方法,它是對特定Class對象的一個引用,方法就是在那個Class對象裡實現的。
剩余的自變量代表傳遞到固有方法調用裡的Java對象。主類型也是以這種形式傳遞的,但它們進行的“按值”傳遞。
在後面的小節裡,我們准備講述如何從一個固有方法的內部訪問和控制JVM,同時對上述代碼進行更詳盡的解釋。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved