不满意 Link 尽管 dll 位于正确的目录中但仍然出错
Unsatisfied Link Error despite dll being in the correct directory
在这里迷路了。所以我有这个 Spring 应用程序,它在开始时以这种方式在主 class:
中加载我的 .dll(自定义)
static {
File f = new File("src/lib/lib.dll");
if(f.exists() && !f.isDirectory()) {
String libDllPath = f.getParentFile().getAbsolutePath();
log.info("libDllPath: {}", libDllPath);
System.setProperty( "java.library.path", libDllPath);
Field fieldSysPath = null;
try {
fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
log.info("\"java.library.path\" : {}", System.getProperty("java.library.path"));
System.loadLibrary("lib");
}
else {
log.error("Lib has not been loaded.");
System.exit(-1);
}
}
如果我从 IntelliJ 启动应用程序,那么这段代码运行良好,并且 .dll 实际上正在加载,就像这里建议的那样
记录器的输出是:
11:14:39.287 [main] INFO com.spring.application- libDllPath: D:\Workspace\whatever\spring-application\src\lib
11:14:39.289 [main] INFO com.whatever - "java.library.path" : D:\Workspace\whatever\spring-application\src\lib
作为记录,这是项目目录树:
src
|----lib
|----lib.dll
|----main
|----java
|----com.main.package
|----resources
|----test
所以我使用 Gradle 从这个应用程序构建了 jar 文件,并尝试在 Windows Server 2012 上部署该应用程序,因为这是该应用程序的目标 OS。
在那里,我正在使用 java -jar spring-application-1.0-SNAPSHOT.jar
将 jar 文件部署到某个默认文件夹中(我尝试在我正在开发应用程序的 Windows10 下部署相同的 jar - 就像一个魅力)和这个我得到的是:
C:\Users\user\Downloads>java -jar spring-application-1.0-SNAPSHOT.jar
11:27:55.841 [main] INFO com.spring.application - libDllPath: C:\Users\user\Downloads\src\lib
11:27:55.853 [main] INFO com.spring.application - "java.library.path" : C:\Users\user\Downloads\src\lib
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\user\Downloads\src\lib\lib.dll: Can't find dependent libraries
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.load0(Unknown Source)
at java.lang.System.load(Unknown Source)
at com.spring.application.<clinit>(SpringApplication.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
我正在确保我的目录中确实有 .dll。
我也试过 运行 将 -Djava.library.path=
的 jar 设置为带有 .dll 的目录,但同样的情况发生了。
有人能告诉我这是怎么回事吗?
很明显,它不起作用的原因是 dll 本身依赖于 MSCVP120D.dll
和 MSCVR120D.dll
。我使用 Dependency Walker 程序在 Windows Server 2012 上追踪到这两个 dll 都不可用。
为了克服这个问题,使用 Visual Studio 2013 编译器 (C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat)
的编译应该是 运行 以及 /MTd
标志,如 post 中所述:
在这里迷路了。所以我有这个 Spring 应用程序,它在开始时以这种方式在主 class:
中加载我的 .dll(自定义)static {
File f = new File("src/lib/lib.dll");
if(f.exists() && !f.isDirectory()) {
String libDllPath = f.getParentFile().getAbsolutePath();
log.info("libDllPath: {}", libDllPath);
System.setProperty( "java.library.path", libDllPath);
Field fieldSysPath = null;
try {
fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
log.info("\"java.library.path\" : {}", System.getProperty("java.library.path"));
System.loadLibrary("lib");
}
else {
log.error("Lib has not been loaded.");
System.exit(-1);
}
}
如果我从 IntelliJ 启动应用程序,那么这段代码运行良好,并且 .dll 实际上正在加载,就像这里建议的那样
记录器的输出是:
11:14:39.287 [main] INFO com.spring.application- libDllPath: D:\Workspace\whatever\spring-application\src\lib
11:14:39.289 [main] INFO com.whatever - "java.library.path" : D:\Workspace\whatever\spring-application\src\lib
作为记录,这是项目目录树:
src
|----lib
|----lib.dll
|----main
|----java
|----com.main.package
|----resources
|----test
所以我使用 Gradle 从这个应用程序构建了 jar 文件,并尝试在 Windows Server 2012 上部署该应用程序,因为这是该应用程序的目标 OS。
在那里,我正在使用 java -jar spring-application-1.0-SNAPSHOT.jar
将 jar 文件部署到某个默认文件夹中(我尝试在我正在开发应用程序的 Windows10 下部署相同的 jar - 就像一个魅力)和这个我得到的是:
C:\Users\user\Downloads>java -jar spring-application-1.0-SNAPSHOT.jar
11:27:55.841 [main] INFO com.spring.application - libDllPath: C:\Users\user\Downloads\src\lib
11:27:55.853 [main] INFO com.spring.application - "java.library.path" : C:\Users\user\Downloads\src\lib
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\user\Downloads\src\lib\lib.dll: Can't find dependent libraries
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.load0(Unknown Source)
at java.lang.System.load(Unknown Source)
at com.spring.application.<clinit>(SpringApplication.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
我正在确保我的目录中确实有 .dll。
我也试过 运行 将 -Djava.library.path=
的 jar 设置为带有 .dll 的目录,但同样的情况发生了。
有人能告诉我这是怎么回事吗?
很明显,它不起作用的原因是 dll 本身依赖于 MSCVP120D.dll
和 MSCVR120D.dll
。我使用 Dependency Walker 程序在 Windows Server 2012 上追踪到这两个 dll 都不可用。
为了克服这个问题,使用 Visual Studio 2013 编译器 (C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat)
的编译应该是 运行 以及 /MTd
标志,如 post 中所述: