java挪用固有要领
当前位置:以往代写 > JAVA 教程 >java挪用固有要领
2019-06-14

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,同时对上述代码举办更详尽的表明。

    关键字:

在线提交作业