zoukankan      html  css  js  c++  java
  • 转载JNI(Windows) 规格严格

    Windows平台上使用MinGW GCC编译JNI动态链接库会在Java加载的时候出错,本文简单介绍其中的原因和应对策略。这里只是简单示范如何用MinGW GCC去编译JNI程序

    第一步:编写java程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    //Test.java
    public class Test {
    	public static native void print();
    	static {
    		System.loadLibrary("hello");
    	}
     
    	public static void main(String[] args) {
    		//打印Java加载DLL文件路径,应该包括当前目录,也就是"."
    		//System.out.
    		//println(System.getProperty("java.library.path"));
    		Test.print();
    	}
    }

    注意其中的代码:public static native void print();

    意思是声明print()这个方法是本地方法而且是静态方法哦,需要在jni中实现。

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

    意思是载入库文件,意味着我们下面的jni程序最终需要打包成hello.dll

    第二步:编译java程序

    javac Test.java

    第三步:生成头文件

    javah -classpath .\bin -d src Test

    -classpath .\bin是指定Test.class文件在当前目录的子目录bin里面

    -d src 是指把生产的Test.h文件放到当前目录下的src子目录下面

    第四步:编写本地实现代码

    我们打开第三步生成的Test.h这个文件,找到其中的方法声明:

    JNIEXPORT void JNICALL Java_Test_print(JNIEnv *, jobject);

    这是jni的命名规范,具体可以参考java tutorial。这里只是方法声明,现在我们来实现它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    /* Test.cpp */
    #include "Test.h"
    #include <iostream>
    using namespace std;
     
    JNIEXPORT void JNICALL Java_Test_print(JNIEnv *, jclass)
    {
    	cout<<"Cpp,Java and JNI~"<<endl;
    }

    第五步:创建库文件

    前面第一步里面提到过hello.dll,这里利用以前提到的制作动态库的命令来生成它:

    g++ -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -shared -o hello.dll Test.cpp

    运行:java Test

    不好,出错了:

    Exception in thread "main" java.lang.UnsatisfiedLinkError: print

    at Test.print(Native Method)

    at Test.main(HelloWorld.java:11)

    意思是库文件已经成功载入了,但是没有找到相匹配的print这个方法。可是我们明明实现了这个方法的呀?原来程序在调用动态库的时候,没有我们想象中的那么简单,而且不同的编译器做法不一样,windows版java中调用jni遵从的是vc的调用方式,和我们用的MinGW GCC默认格式不一致。我们需要调整一下参数,(注意其中的–kill-at):

    g++ -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -shared -Wl,--kill-at -o hello.dll Test.cpp

    如果你在程序里面没有使用了C++的函数库,那么把g++换成gcc就可以了。另外,也可以把jni.h jni_md.h两个文件拷贝到源文件目录下面,这样的话就可以不用指定-I参数了,编译也更方便一些。例如,我把Test.h,Test.cpp和jni.h jni_md.h放在一起,然后可以使用命令:

    g++ -shared -Wl,--kill-at -o hello.dll Test.cpp

    运行:java Test

    显示:Cpp,Java and JNI~

    运行成功!

  • 相关阅读:
    javascript判断触发事件event的鼠标按钮
    解决IE8 Session共享问题
    SignalR 实现web浏览器客户端与服务端的推送功能
    MFC ActiveX控件与ATL ActiveX控件的比较 .
    rpm relevent operation record
    通过rpm包安装、配置及卸载mysql的详细过程 Richard Shen 运维/架构 51CTO技术博客
    instal python relevent cmds
    ubuntu日志的设置
    关于电信、网通检测ADSL共享上网的技术手段
    Simple usage of Python's logging module
  • 原文地址:https://www.cnblogs.com/diyunpeng/p/1689715.html
Copyright © 2011-2022 走看看