好长时间没写博客了,最近感觉学了好多知识,学习了redis,看了redis几种数据结构的源码,还看了《鸟哥的Linux私房菜》这本书大半部分,还有我们项目用到的许多知识点,特别是RMI,还有maven的相关知识,好多实用的工具类,但是一直没有时间仔细的总结一下,感觉学的还是不够深入、不够扎实。今天写项目时要用到图片压缩功能,我在网上找到了一个现成的程序,里面要引入几个类,但是我不想引入整个jar包了,于是就单独把这几个类反编译后放到我的项目中了,程序都没有报错,但是运行时报错了,我打断点后发现错误是出现在这里:
private native void initEncoder(Class paramClass);
这个用了native关键字,native修饰的方法Java是不会给它提供实现体的,一般是由别的编程语言(如C)提供实现,因为一些与硬件交互的操作Java实现起来非常困难,而C语言就十分方面。
因为Java没有提供initEncoder的实现体,所以程序走到这里就报错了,所以我就开始在网上搜资料学习一下JNI。
主要测试都是参考这篇文章:点击打开链接,但是关于生成dll文件该文章没有详细说,我上网看了一些资料后用dev c++生成了dll文件(实在不想装vc6.0)。
正如文章所说,首先建立一个Java文件:
class HelloWorld
{
public native void displayHelloWorld();
static {
System.loadLibrary("hello");
}
public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
}
上面的
displayHelloWorld()方法是native类型的,说明Java不会给它提供实现体,之后我们会在C程序提供这个方法;static静态块中的
System.loadLibrary("hello");意思是当该类加载入内存后会加载一个名为hello的dll文件,该dll文件中有
displayHelloWorld()方法的实现,所以main方法中再调用
displayHelloWorld()方法时就不会报错了。
然后我们用javac命令编译出上面Java文件的class文件HelloWorld.class,再用javah命令”javah HelloWorld"生成HelloWorld.h文件。
关于javah命令:点击打开链接
下面就该生成dll文件了,这个比较费事(对于没有C/C++经验的程序员来说),不同的IDE生成dll文件的方式不一样,我是用devc++生成的,方法如下:
1,先在devc++中建立一个dll的工程,会自动有两个文件,主要是dllmain.c文件:这里写你要实现的方法,但方法名不是上面displayHelloWorld()方法,需要打开HelloWorld.h文件,发现我们要实现的方法原型是:
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
(JNIEnv *, jobject);
2,在dllmain.c中首先包含HelloWorld.h文件、还有dll.h文件(该文件在jdk目录下的include目录中可以找到),dllmain.c中内容是:
#include "dll.h"
#include "HelloWorld.h"
#include <windows.h>
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj){
printf("Hello world!/n");
return;
}
然后编译整个项目就生成我们需要的dll文件了,因为Java程序中的静态块中加载的dll文件名是"hello",所以我们可以把这个dll文件改名为hello,然后放到和Java文件同一目录下,然后在用java命令执行class文件就可以了。
写的比较匆忙,可能刚接触JNI的同学还不能从本文中直接学会JNI,其实主要是生成dll文件时可能会遇到麻烦,这个多上网搜集些资料应该也不会花费太多时间的。