Java
语言基础

System.load(String)和System.loadLibrary(String)

简介:JDK提供给用户了两个方法用于载入文件,一个是`System.load(String filename)`方法,另外一个是`System.loadLibrary(String libname)`方法。

JDK提供给用户了两个方法用于载入文件,一个是System.load(String filename)方法,另外一个是System.loadLibrary(String libname)方法,下面是这两个方法的区别:

  1. 它们都可以用来装载库文件,不论是JNI库文件还是非JNI库文件。在任何本地方法被调用之前必须先用这个两个方法之一把相应的JNI库文件装载。
  2. System.load(String filename)在JDK API中的描述是“从作为动态库的本地文件系统中以指定的文件名加载代码文件。文件名参数必须是完整的路径名。”,因此该方法的参数为库文件的绝对路径,可以是任意路径。例如你可以这样载入一个Windows平台下JNI库文件:System.load("C://Documents and Settings//TestJNI.dll");
  3. System.loadLibrary(String libname)在JDK API中的描述是“加载由libname参数指定的系统库。将库名映射到实际系统库的方法取决于系统。”,因此该方法的参数为库文件名,不包含库文件的扩展名。例如你可以这样载入一个Windows平台下JNI库文件:System.loadLibrary("TestJNI");

这里,TestJNI.dll必须是在java.library.path这一JVM变量所指向的路径中。可以通过System.getProperty("java.library.path");来获得该变量的值:

  • public static void main(String[] args) {
  • System.out.println(System.getProperty("java.library.path"));
  • }

打印结果如下:

  • C:\Java\jdk1.8.0_144\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\ProgramData\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Java\jdk1.8.0_144\bin;C:\Java\jdk1.8.0_144\jre\bin;C:\Program Files\MySQL\MySQL Server 5.5\bin;C:\Java\apache-maven-3.5.4\bin;C:\Java\hadoop-2.7.2\bin;C:\Java\hadoop-2.7.2\sbin;D:\Program Files (x86)\Rational\common;C:\Java\protoc-2.5.0-win32;D:\Program Files (x86)\Pandoc\;D:\Program Files (x86)\Calibre2\;D:\Program Files\node-v9.10.1-win-x64\;C:\IDE\JetBrains\WebStorm 2017.2\bin\;C:\Java\scala-2.11.8\bin;D:\Program Files\Sublime Text 3;D:\Program Files\Python\Python36;D:\Program Files\Python\Python27;D:\Program Files\Python\Python27\Scripts;D:\Program Files\Python\Python36\Scripts;D:\Program Files\TortoiseGit\bin;C:\Java\akka-2.4.16\bin;D:\Program Files\nginx-1.12.2;D:\Program Files\Redis-x64-3.2.100;C:\WINDOWS\System32\OpenSSH\;D:\Program Files (x86)\Netcat;d:\Program Files\Git\cmd;C:\Program Files\MySQL\MySQL Server 5.7\bin;C:\Java\btrace-bin-1.3.1\bin;D:\Java\elasticsearch-5.2.0\bin;D:\Java\kibana-5.2.0-windows-x86\bin;D:\Program Files\mongodb-win32-x86_64-2008plus-ssl-3.6.4\bin;d:\Users\limyr\Miniconda3;d:\Users\limyr\Miniconda3\Library\mingw-w64\bin;d:\Users\limyr\Miniconda3\Library\usr\bin;d:\Users\limyr\Miniconda3\Library\bin;d:\Users\limyr\Miniconda3\Scripts;C:\Users\limyr\AppData\Local\Microsoft\WindowsApps;D:\Program Files\Fiddler;.

默认情况下,在Windows平台下,该值包含如下位置:

  • 和JRE相关的一些目录;
  • 程序当前目录;
  • Windows目录;
  • 系统目录(System32);
  • 系统环境变量Path指定目录。

如果你要载入的库文件静态链接到其它动态链接库,例如TestJNI.dll,静态链接到dependency.dll,需要注意以下两点:

  • 如果你选择System.load("C://Documents and Settings//TestJNI.dll");,那么即使你把dependency.dll同样放在C://Documents and Settings//下,System.load(String filename)方法还是会因为找不到依赖的dll而失败。因为JVM在载入TestJNI.dll会先去载入TestJNI.dll所依赖的库文件dependency.dll,而dependency.dll并不位于java.library.path所指定的目录下,所以jvm找不到dependency.dll。有两个方法解决这个问题:一是把C://Documents and Settings//加入到java.library.path的路径中,例如加入到系统的path中。二是先调用
    System.load("C://Documents and Settings//dependency.dll");让JVM先载入dependency.dll,然后再调用System.load("C://Documents and Settings//TestJNI.dll");

  • 如果选择System.loadLibrary("TestJNI");,那么你只要把dependency.dll放在任何java.library.path包含的路径中即可,当然也包括和TestJNI.dll相同的目录。