jni中关于dll的装载问题[转]

   通常我们在写大型项目时,也就是集成的项目时,单独用JAVA语言去完成所有的事情往往效果不佳,也不能很好的完成,例如:我们要去调硬件,获取电脑的运行状况等等(如果用JAVA语言实现时,往往耗时),基于此,我们就要寻求一种很好的解决方案,那就是利用别的语言的长处了,如:C++(它在对底层的调用和硬件方面确实够强悍)。如果我们能用C++实现对硬件的所有操作,然后我们再用JAVA去调C++实现的东西,那不是很完美了,鉴于这样的情况,我们的JNI就应运而生了,我们都知道,JNI调C++实现的东西也就是去调C++运行时生成的*.DLL文件,此时问题就出现了,我们通常调DLL都用1、System.load(String filename);  //指定加载的dll全路径文件名;2、System.LoadLibrary(String dllname);  //指定加载的dll名(无path,无后缀),这两种方法很坑爹,如要你利用Eclipse编辑工具时,你必须指定它的本机库位置(点击项目右键属性-》JAVA构造路径-》源代码下拉-》本地库位置-》编缉指定文件后搞定),否则你打死它它也说找不到DLL资源(反正我试了是没有行,也许我的RP值不够吧!),如果你指定了它的本机库位置了,先恭喜你,此时你运行在你的机子上确实成功了,但是,你不要高兴得早,试想,你在这是写死了的,那放到别的机子上,它还能跑起来吗,在这,我可以很负责任的告诉你,那是不行的,这样不是和我们的JAVA程序编译一次,到处跑相悖了吗,你读到这可能受不了,那我应怎么解决呢?你要相信,一个问题的产生肯定有它的解决方法,它的解决方法也许有上百种,你才用一两种就放弃了,那不是太可惜了,所以,接下来就是见证奇迹的时候了,具体方法如下:我在程序中的代码如下

public class HelloWorld {

--------------静态代码块就是动态的获取DLL,这样后你就跟上JAVA程序编译一次,到处跑的步伐了-------------------------------

 static {
  try {
   String libpath = System.getProperty("java.library.path");
   if (libpath == null || libpath.length() == 0) {
    throw new RuntimeException("java.library.path is null");
   }

   String path = null;
   StringTokenizer st = new StringTokenizer(libpath, System
     .getProperty("path.separator"));
   if (st.hasMoreElements()) {
    path = st.nextToken();
   } else {
    throw new RuntimeException("can not split library path:"
      + libpath);
   }

   Class thisClass = HelloWorld.class;
   InputStream inputStream = thisClass.getResource("HelloWorld.dll")
     .openStream();
   File dllFile = new File(new File(path), "HelloWorld.dll");
   if (!dllFile.exists()) {
    FileOutputStream outputStream = new FileOutputStream(dllFile);
    byte[] array = new byte[8192];
    for (int i = inputStream.read(array); i != -1; i = inputStream
      .read(array)) {
     outputStream.write(array, 0, i);
    }
    outputStream.close();
    // System.loadLibrary("RegistryUtil");
   }

    System.loadLibrary("HelloWorld");//这样加载的DLL就不用去指定什么本机库位置了

  } catch (UnsatisfiedLinkError e) {
   throw e;
  } catch (Throwable e) {
   throw new RuntimeException("load RegistryUtil.dll error!", e);
  }
 }

 

 public native void sayHello();// 表示要在c++本地实现的方法

 

 public static void main(String[] args) {
  new HelloWorld().sayHello();
 }

 

}

 

 

接下来就是如何把DLL也打进JAR包里吧,其实so easy,你只要把整个项目都导出就可以了,这样你的JAR包里就有了DLL文件,此时就功德圆满了。

原文地址:https://www.cnblogs.com/spinsoft/p/2628415.html