如何在我的Web应用程序中加载自定义dll文件?我尝试了以下方法:
- 复制
system32
文件夹中所有必需的dll,并尝试在Servlet
构造函数中加载其中一个System.loadLibrary
- 将所需的dll复制到
tomcat_home/shared/lib
和tomcat_home/common/lib
所有这些dll都在WEB-INF/lib
Web应用程序中
如何在我的Web应用程序中加载自定义dll文件?我尝试了以下方法:
system32
文件夹中所有必需的dll,并尝试在Servlet
构造函数中加载其中一个System.loadLibrary
tomcat_home/shared/lib
和tomcat_home/common/lib
所有这些dll都在WEB-INF/lib
Web应用程序中
Answers:
为了System.loadLibrary()
正常工作,该库(在Windows上为DLL)必须位于系统属性中列出的目录中PATH
或您的路径中的某个目录中java.library.path
(以便您可以像这样启动Java java -Djava.library.path=/path/to/dir
)。
此外,对于loadLibrary()
,您可以指定库的基本名称,但不要.dll
在末尾添加。因此,/path/to/something.dll
您只需使用即可System.loadLibrary("something")
。
您还需要查看所获得的确切信息UnsatisfiedLinkError
。如果显示类似以下内容:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no foo in java.library.path
则无法在您的或中找到foo库(foo.dll)。如果显示类似以下内容:PATH
java.library.path
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()V
那么库本身就出现了问题,即Java无法将应用程序中的本机Java函数映射到其实际本机副本。
首先,我会在您的System.loadLibrary()
呼叫周围记录一些日志,以查看该呼叫是否正常执行。如果它引发异常或不在实际执行的代码路径中,那么您将始终得到UnsatisfiedLinkError
上面解释的后一种类型。
loadLibrary()
附带说明一下,大多数人使用本机方法将调用放入类中的静态初始化程序块中,以确保始终将其执行一次:
class Foo {
static {
System.loadLibrary('foo');
}
public Foo() {
}
}
loadLibrary()
备注-当您不知道自己在做什么错时,此功能非常有用。
lib
前缀。所以System.loadLibrary("foo")
需要libfoo.so
。
在运行时更改'java.library.path'变量是不够的,因为JVM只能读取一次。您必须像这样重置它:
System.setProperty("java.library.path", path);
//set sys_paths to null
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
请在以下位置进行抢劫:在运行时更改Java库路径。
亚当·巴特金(Adam Batkin)的原始答案将带您找到解决方案,但是,如果重新部署Web应用程序(而不重新启动Web容器),则应遇到以下错误:
java.lang.UnsatisfiedLinkError: Native Library "foo" already loaded in another classloader
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1715)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1646)
at java.lang.Runtime.load0(Runtime.java:787)
at java.lang.System.load(System.java:1022)
发生这种情况的原因是,最初加载DLL的ClassLoader仍引用此DLL。但是,您的Web应用程序现在正在使用新的ClassLoader运行,并且由于正在运行相同的JVM,并且JVM不允许2对同一DLL的引用,因此无法重新加载它。因此,您的Web应用程序无法访问现有的DLL,也无法加载新的DLL。所以...。
Tomcat的ClassLoader文档概述了重新加载的Webapp为什么要在新的隔离的ClassLoader中运行,以及如何解决此限制(在很高的层次上)。
解决方案是将Adam Batkin的解决方案扩展一点:
package awesome;
public class Foo {
static {
System.loadLibrary('foo');
}
// required to work with JDK 6 and JDK 7
public static void main(String[] args) {
}
}
然后将一个仅包含此已编译类的jar放入TOMCAT_HOME / lib文件夹中。
现在,在您的webapp中,您只需要强制Tomcat引用该类,就可以像这样简单地完成:
Class.forName("awesome.Foo");
现在,您的DLL应该已加载到通用的类加载器中,并且即使重新部署后也可以从您的web应用程序中引用它。
合理?
可以在Google代码static-dll-bootstrapper上找到有效的参考副本。
您可以使用System.load()
提供所需路径的绝对路径,而不是提供各个操作系统的标准库文件夹中的文件。
如果要使用本机应用程序,请使用System.loadLibrary(String filename)
。如果您想提供自己的,最好使用load()。
您还应该能够正确使用loadLibrary
该java.library.path
套件。请参阅ClassLoader.java
以获取实现源,其中显示了两个被检查的路径(OpenJDK)
如果问题是System.loadLibrary找不到有问题的DLL,则一个常见的误解(由Java的错误消息强化)是系统属性java.library.path是答案。如果将系统属性java.library.path设置为DLL所在的目录,则System.loadLibrary确实会找到您的DLL。但是,如果您的DLL(通常)又依赖于其他DLL,则java.library.path无法提供帮助,因为从属DLL的加载完全由操作系统管理,而操作系统对java.library一无所知。路径。因此,在启动JVM之前,绕过java.library.path并简单地将DLL的目录添加到LD_LIBRARY_PATH(Linux),DYLD_LIBRARY_PATH(MacOS)或Path(Windows)几乎总是更好的选择。
(注意:我在DLL或共享库的一般意义上使用术语“ DLL”。)
对于那些正在寻找 java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path
我面临着同样的例外;我尝试了所有事情,并使它起作用的重要事情是:
它与tomcat 6一起使用。
我使用的是Mac OS X Yosemite和Netbeans 8.02,遇到了相同的错误,发现的简单解决方案与上面类似,当您需要在项目中包括本机库时,这很有用。Netbeans的下一个也是:
1.- Right click on the Project
2.- Properties
3.- Click on RUN
4.- VM Options: java -Djava.library.path="your_path"
5.- for example in my case: java -Djava.library.path=</Users/Lexynux/NetBeansProjects/NAO/libs>
6.- Ok
我希望它对某人有用。我找到解决方案的链接在这里: java.library.path –它是什么以及如何使用
VM Options: java -Djava.library.path="your_path"
我遇到了同样的问题,错误是由于dll重命名所致。库名称也可能写在dll内的某处。当我放回原名时,我可以使用System.loadLibrary