国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
JNI示例
JNI示例
2007年05月27日 星期日 16:15
一、JNI簡介
JNI:Java Native Interface,是Java語言提供的一種通用接口,用于Java代碼與本地化代碼的交互。所謂本地化代碼是指直接編譯成的與機(jī)器相關(guān)的二進(jìn)制代碼,而非Java字節(jié)碼之類的中間代碼。Windows下面的可執(zhí)行文件,DLL等,Linux下面的可執(zhí)行文件和SO文件等,都是二進(jìn)制代碼。
JNI允許Java語言編寫的程序與其他語言編寫的程序庫(DLL, SO)或可執(zhí)行文件進(jìn)行互操作,包括匯編、C、C++。JNI產(chǎn)生的原因在于以下幾種需求:
(1). 你的應(yīng)用程序需要使用系統(tǒng)相關(guān)的功能,而Java代碼不支持或是難以辦到。這個(gè)比較典型的是實(shí)現(xiàn)托盤圖標(biāo),有幾種現(xiàn)成的方案都是用的JNI做的,名字好像是叫做TrayIcon和StayOnTop。當(dāng)然啦,如果是用的Java1.6,那就要另當(dāng)別論了。
(2). 已有其他語言寫好的類庫或程序,希望Java程序可以使用它們。
(3). 出于更高的性能要求,希望使用匯編或是C/C++語言來實(shí)現(xiàn)部分功能。
下圖出自JNI Tutorial,展示了JNI的地位:

其他的理論的東西就不多說了,JNI Tutorial講得很清楚。強(qiáng)烈建議閱讀。

二、JNI的開發(fā)步驟
這里以使用C++編寫本地化方法實(shí)現(xiàn)為例,開發(fā)一個(gè)使用JNI的Demo程序,具體步驟如下所示:
(1). 編寫帶有native方法的java類
(2). 使用javac命令編譯所編寫的java類
(3). 使用javah命令處理類文件,生成C/C++頭文件
(4). 使用C/C++實(shí)現(xiàn)本地方法
(5). 將C/C++編寫的文件生成動(dòng)態(tài)連接庫

三、Demo程序,Demo程序宣示了Java代碼中調(diào)用C++的輸出功能打印字符串,同時(shí)演示了使用C++的輸入功能讀取字符串,并使用System.out.println輸出。

1. 編寫帶native方法的Java類
本示例中的源程序就一個(gè)Java類。如下所示:
// HelloJNI.java -- 簡單的JNI入門示例。
// 2007-4-5 16:41:45

public class HelloJNI {
  public native void displayHello();
  public native void showTime();

  private native String getLine(String prompt);

  static {
    System.loadLibrary("hello");
  }

  public static void main(String[] args) throws Exception {
    HelloJNI hj = new HelloJNI();

    System.out.println("==> Demo 1: hello");
    hj.displayHello();
    System.out.println("==> Demo 2: time");
    hj.showTime();

    System.out.println("==> Demo 3: input");
    String input = hj.getLine("Type a line: ");
    System.out.println("User typed: " + input);
  }
}

說明:一共3個(gè)native方法,第一個(gè)簡單的Hello,第二個(gè)使用<ctime>頭文件中的相關(guān)函數(shù)計(jì)算當(dāng)前時(shí)間,第三個(gè)讀取輸入。注意static語句塊:
static {
        System.loadLibrary("hello");
}
在JVM載入HelloJNI類的時(shí)候加載動(dòng)態(tài)庫,System.loadLibrary()中的參數(shù)是我們要生成的動(dòng)態(tài)庫文件的名字,不包括擴(kuò)展名,在Windows下面是hello.dll,Linux下面是hello.so,這個(gè)由Java自動(dòng)識(shí)別。

2. 編譯此類

3. javah HelloJNI 生成C/C++頭文件,生成的頭文件不用任何修改。如下所示:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNI */

#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:      HelloJNI
* Method:     displayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_displayHello
  (JNIEnv *, jobject);

/*
* Class:      HelloJNI
* Method:     showTime
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_showTime
  (JNIEnv *, jobject);

/*
* Class:      HelloJNI
* Method:     getLine
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_HelloJNI_getLine
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif



4. 編寫C/C++實(shí)現(xiàn)文件,如下所示:
// HelloJNIImpl.cpp -- 自己編寫的實(shí)現(xiàn)文件
// 2007-4-5 16:52:53

#include <jni.h>
#include <iostream>
#include <ctime>
#include <string>
#include <cstdio>
#include <windows.h>
#include "HelloJNI.h"

extern "C" {
  //
}

using namespace std;

JNIEXPORT void JNICALL Java_HelloJNI_displayHello(JNIEnv * env, jobject obj) {
  cout << "Hello, JNI tech. This is from C++!" << endl;
}

JNIEXPORT void JNICALL Java_HelloJNI_showTime(JNIEnv * env, jobject obj) {
  time_t sec;
  tm t;

  time_t loop;

  cout << "時(shí)間:";
  sec = time(NULL);
  t = *localtime(&sec);
  unsigned int hour = t.tm_hour;
  unsigned int mini = t.tm_min;
  unsigned int secd = t.tm_sec;
  
  if(hour < 10) {
  cout << "0" << hour;
  }
  else {
    cout << hour;
  }
  cout << ":";
  if(mini < 10) {
    cout << "0" << mini;
  }
  else {
    cout << mini;
  }
  cout << ":";
  if(secd < 10) {
    cout << "0" << secd;
  }
  else {
    cout << secd;
  }
  cout << endl;
}

JNIEXPORT jstring JNICALL Java_HelloJNI_getLine(JNIEnv * env, jobject obj, jstring prompt) {
  char buf[128] = {0};
  const char * str = (env)->GetStringUTFChars(prompt, 0);
//   printf("%s", str);
  cout << str;
  (env)->ReleaseStringUTFChars(prompt, str);
  string buffer;
  getline(cin, buffer);
//   scanf("%s", buf);
  return (env)->NewStringUTF(buffer.c_str());
}

說明:JNI Tutorial中使用的居然是像下面這樣的代碼,env指針的使用應(yīng)該有誤,敬請(qǐng)注意。
JNIEXPORT jstring JNICALL
Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const char *str = (*env)->GetStringUTFChars(env, prompt, 0);
printf("%s", str);
(*env)->ReleaseStringUTFChars(env, prompt, str);
...

5. 生成本地庫文件。筆者使用的VS.NET 2003中的C++編譯器。VS.NET 2003命令行工具生成DLL的命令:
cl -I<頭文件目錄1> -I<頭文件目錄2> -LD <C/C++源文件名> -Fe<生成的DLL文件名>
-I選項(xiàng)指定頭文件目錄,-LD指定C++源文件,-Fe指定生成的DLL文件名。將各個(gè)部分替換成實(shí)際的情況,實(shí)際使用的命令如下:
cl -IC:/java/jdk1.5.0_10/include -IC:/java/jdk1.5.0_10/include/win32 -LD HelloJNIImpl.cpp -Fehello.dll
注:cl可以增加-EHsc參數(shù)來減少生成過程中的輸出信息。如下圖所示:

6. 運(yùn)行結(jié)果,如下圖所示:

注意自己輸入的那一行!

7. 自動(dòng)化。其實(shí)步驟都很簡單,所以可以使用Ant來完成。下面提供一個(gè)ANT Buildfile。使用之前請(qǐng)根據(jù)自己的實(shí)際情況修改相關(guān)屬性。
注意:Builfile編碼是UTF-8的。
build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project default="help" basedir="." name="JNI_Hello">
  <property name="app.home" value="."></property>

  <!-- 設(shè)置頭文件的目錄,根據(jù)JDK具體的安裝目錄而定 -->
  <property name="h.dir1" value="C:/java/jdk1.5.0_10/include"></property>
  <property name="h.dir2" value="C:/java/jdk1.5.0_10/include/win32"></property>
  
  <!-- 設(shè)置cl工具的路徑,視具體情況而定 -->
  <property name="vc.bin.dir"
    value="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/bin">
  </property>

  <property name="cpp.name" value="HelloJNIImpl.cpp"></property>
  <property name="dll.name" value="hello.dll"></property>

  <target name="compile" description=" ==> 編譯Java源文件">
    <javac srcdir="${app.home}" destdir="${app.home}">
    </javac>
  </target>

  <target name="javah" description=" ==> 生成C/C++頭文件">
    <javah destdir="${app.home}" force="yes" class="HelloJNI"/>
  </target>
  
  <target name="dll" description=" ==> 調(diào)用cl命令生成相關(guān)的DLL文件">
    <exec dir="${app.home}" executable="${vc.bin.dir}/cl.exe" os="Windows XP">
      <!-- 參數(shù)-EHsc好像是VS.NET2003中cl.exe的,可以不加,參考下面的注釋行 -->
      <arg line="-EHsc -I${h.dir1} -I${h.dir2} -LD ${cpp.name} -Fe${dll.name}"/>
      <!--
      <arg line="-I${h.dir1} -I${h.dir2} -LD ${cpp.name} -Fe${dll.name}"/>
      -->
    </exec>
  </target>

  <target name="run" description=" ==> 運(yùn)行">
    <java classname="HelloJNI"></java>
  </target>

  <target name="all" description=" ==> 自動(dòng)進(jìn)行上面任務(wù)列表">
    <antcall target="compile"/>
    <antcall target="javah"/>
    <antcall target="dll"/>
    <antcall target="run"/>
  </target>

  <target name="help" description=" ==> 顯示幫助信息">
    <echo>用法幫助:</echo>
    <echo>ant compile      編譯Java源文件</echo>
    <echo>ant javah        生成C/C++頭文件</echo>
    <echo>ant dll          調(diào)用cl命令生成相關(guān)的DLL文件</echo>
    <echo>ant run          運(yùn)行</echo>
    <echo></echo>
    <echo>ant all          自動(dòng)進(jìn)行上面任務(wù)列表</echo>
    <echo>ant help         顯示幫助信息</echo>
  </target>
</project>

Done!^_^!

JNI還有很多高級(jí)的功能,這里我就不說了,一來是不太會(huì),二來也沒什么意義。JNI Tutorial上講得很全面,不錯(cuò)。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
JNI編程進(jìn)階
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服