以下内容转载自 Thinking in java
调用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对象。主类型也是以这种形式传递的,但它们进行的“按值”传递。

解决方案 »

  1.   

    写一个bean来封装对native方法的调用,然后在程序中使用该bean,不过一定要注意资源管理问题
    在有的时候根据项目的需要不可以避免用到本地的东西,最常见的就是java想访问Window本地的东东,比如想调节鼠标移动速度、改变窗体底色、甚至用javaApplet做个基于windows的远程控制象pcanywhere那样,怎么办?下面就用个最简单的例子来入门。步骤
    写一个HelloWorld.java 
    class HelloWorld {
        public native void displayHelloWorld();//定义本地方法
        static {
            System.loadLibrary("hello");//调入本地库
        }
        
        public static void main(String[] args) {
            new HelloWorld().displayHelloWorld();
        }}以上代码看起来好象和以前写的有点区别,出现了native关键字,但是不用太深究,你可以把这段代码看成是调用本地库的桥。
    然后java HelloWorld.java生成HelloWorld.class生成C的头文件
    很简单,就用jdk提供的javah命令javah HelloWorldclass(注意,如果运行出错就把classpath指向class),成功运行后会出现HelloWorld.h 
    /* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>
    /* Header for class HelloWorld */#ifndef _Included_HelloWorld#define _Included_HelloWorld#ifdef __cplusplusextern "C" {#endif
    /*
     * Class:     HelloWorld
     * Method:    displayHelloWorld
     * Signature: ()V
     */JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
      (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif编写C文件并编译成DLL 
    #include <jni.h>#include "HelloWorld.h"#include <stdio.h>#include <windows.h>JNIEXPORT void JNICALLJava_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj){
        printf("Hello world!\n");//在这里实现java类中定义的方法
        MessageBeep(0);//调用到win本地,会发一声响
        return;}文件名随便取,主要扩展名.c就可以。相信有C基础的人都可以明白以上的代码。然后利用你拿手的工具,不管是BCB或VC++或者用命令行编译出DLL。
    windows VC用
    cl -Ic:\java\include -Ic:\java\include\win32
    -LD HelloWorldImp.c -Fehello.dll
    最后,DLL的文件名当然要是hello.dll,因为前面的
    System.loadLibrary("hello");//调入本地库运行
    java HelloWorld
    屏幕会打印Hello world!而且伴着Beep一声。你成功了!
    如果运行出现 
    Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.pathat java.lang.ClassLoader.loadLibrary(ClassLoader.java:1410)at java.lang.Runtime.loadLibrary0(Runtime.java:772)at java.lang.System.loadLibrary(System.java:832)at HelloWorld.<clinit>(HelloWorld.java:5)
    那就考虑hello.dll的路径,一般放在和class同个目录就行了。