将JNI的dll添加到jar包并发布和执行的方法

经常会有这种情况,需要用JNI来实现某些java不支持的操作(比如windows上操作智能卡),同时又对此操作实现一定的java层面的封装,并需要发布给第三方开发者进行使用。一般的处理方式是,提供一个jar包,同时提供一个dll,并要求第三方开发者将此dll拷贝到C:/windows/system32目录下。这种操作方式不够傻瓜,最爽的方式当然是和纯java一样,提供一个jar包就全部解决。

 

首先,Java加载JNI的动态库,有两种方式:

    System.load(String filename);  //指定加载的dll全路径文件名

    System.LoadLibrary(String dllname);  //指定加载的dll名(无path,无后缀)

 

很明显Load是绝对路径,LoadLibrary的方式和windows加载dll的方式一样,按当前目录和path系统目录的顺序查找文件。

但这两种显然都不适合动态的部署。因为每个系统的环境变量可能并不完全相同。所以好的方式,是在运行态的时候确定。

思路是:dll在jar包中,也就是属于类的资源,所以可以在类初始化的时候,从Resource里面获得。然后拷贝为一个临时文件,由System.load指定全路径进行加载。并利用临时文件的属性在退出的时候删除。

如此实现:

public class Test{
 static {
  try {
  InputStream in = Switch.class.getClass().getResource("/NTV.dll").openStream();
  File dll = File.createTempFile("NTV", ".dll");
  FileOutputStream out = new FileOutputStream(dll);

  int i;
  byte [] buf = new byte[1024];
  while((i=in.read(buf))!=-1) {
   out.write(buf,0,i);
  }
  
  in.close();
  out.close();
  dll.deleteOnExit();

  System.load(dll.toString());//
  }catch (Exception e) {
   System.err.println("load jni error!");
  }
 }
 public native int func(String str);

 public static void main(String[] args) {

    func("hello");

 }

}

 

在eclipse的项目目录上建立dll目录,将NTV.dll拷贝进来,并将dll目录添加到ClassPath。即能进行调试。在调试OK后,建立ant工程


 

 
  

  
  
   
  

 
 
  
   
   
   
    
    
   

  

 

 

此时dll被添加到jar包的根上,尝试着在任何位置 java -jar */Test.jar 都可以正确的执行。

 

你可能感兴趣的:(码农自留地)