Skip to content

jni path

landon edited this page Sep 14, 2018 · 1 revision

关于Java调用JNI总结

  • 使用jnlua
    • LuaState这个类的静态初始化器会load
    • System.loadLibrary("jnlua5.1")
  • 关于System.loadLibrary的执行过程
    • 网上几乎大部分都是说加载这个库默认是去java.library.path去load
    • 这个说法没有大的问题 但还是有问题的 可以看后面的测试
  • 测试过程1(windows为主)
    • eclipse中首先输出:System.getProperty("java.library.path")
      • 输出结果包括jre的目录/windows库目录/path目录/eclipse目录/当前目录
      • 直接将jnlua5.1.dll扔到jre\bin目录,测试load,可以顺利加载到这个dll
    • 脱离eclipse运行,命令行下输出System.getProperty("java.library.path")
      • 输出结果没有jre的目录和eclipse目录等
      • 直接将jnlua5.1.dll扔到jre\bin目录,测试load,发现也可以顺利load
    • 问题:在命令行下,java.library.path根本没有jre\bin这个目录,为什么也能load成功
  • 测试过程1总结
    • 去看了看System.loadLibrary的源代码{@link ClassLoader#loadLibrary},这里加载库,其实是有两个路径,一个是sys_paths#sun.boot.library.path,另外一个是usr_paths#sun.boot.library.path,而且是前者优先加载的
    • 命令行下输出System.getProperty("sun.boot.library.path"),发现这个路径就是jre\bin目录
    • 第一个总结:
      • System.loadLibrary这个库加载是优先去sun.boot.library.path这个path去加载,如果没有才去java.library.path去加载
    • 第二个总结:
      • eclipse的一些路径输出和命令下的可能不同,不要认为在eclipse下测试通过,在实际命令下就通过,需要实际测试,尤其是涉及到路径相关
  • 测试过程2(windows为主)
    • 加载库的时候,有时候需要加载依赖的库,如jnlua.dll需要依赖lua5.1.dll
    • 那么这个依赖的库是从什么路径加载的呢?
      • java.library.path is for JNI libraries only, not libraries they depend on. The system path is used for those.you should set PATH, LD_LIBRARY_PATH, or DYLD_LIBRARY_PATH (on Windows, Linux, or OSX respectively)
      • 即依赖加载的库是取决于是os本身,对于window来说通常是PATH,对于linux是LD_LIBRARY_PATH
      • 这也解释了为什么你本地如果装了lua(lua会被配置在环境变量),加载jnilua不会报错的原因,因为会默认的去path加载依赖的lua5.1.dll
  • 最终总结(不限于Windows/linux/mac)
    • System.loadLibrary加载路径首先是sun.boot.library.path,然后才是java.library.path
      • 如果找不到则直接抛出java.lang.UnsatisfiedLinkError: no jnlua5.1 in java.library.path
    • 对于加载库所依赖的库加载,是os本身去加载的,和上面jvm的两个路径没有一毛钱关系.通常是如path(windows),ld_library_path(linux)等
      • 如果找不到依赖,则抛出java.lang.UnsatisfiedLinkError: Can't find dependent libraries
    • java.library.path默认包括path/ld_library_path
      • 所以对于加载的库和依赖库的位置最好放在path或者ld_library_path下即可
    • eclipse中输出的路径和命令下输出的路径不同
      • 关于路径的测试一定要实际去测试,否则可能IDE下的结果和命令下的结果不同
    • 不建议启动参数-Djava.library.path 这个会覆盖掉默认的路径,可能会出现一些问题
Clone this wiki locally