在java程序中动态设置java.library.path
最近在做一个项目的过程中需要用到第三方的jar包和动态链接库(dll),其中jar包可以直接引入,问题是在开发的时候dll可以放在System32下,但是当项目完成后build的时候,这种方式就行不通了,所以必须考虑其他的方式来引用所需的dll文件。我们知道,在VM参数处通过-Djava.library.path后将加载路径指定到自己的lib目录后,程序可以正常启动。但这种方式显然不够灵活,受限于
项目目前需要加载几个外部的dll文件,但是每次启动都要手动设置jvm参数就很麻烦,于是就想找能够在运行时动态修改java.library.path的方法
这种方式显然不灵活,那么我们现在就需要采取其他的方式,比如在项目的根目录下建一个dll的文件夹,将要用到的dll文件放到此目录下,然后
通过System类的setProperty函数来在代码中动态的改变一下java.library.path的值。
如下:
System.setProperty("java.library.path","%ProjectPath%/dll");
问题是这种方式是行不通的,会报错"no JIntellitype in java.library.path"。
查找原因:
代码中设置不起作用,主要是因为java.library.path只在jvm启动时读取一次,其他情况下的修改不会起作用的。
中间遇到的坑就就不说了,直接上解决方法
private static void addLibraryDir(String libraryPath) throws Exception {
Field userPathsField = ClassLoader.class.getDeclaredField("usr_paths");
userPathsField.setAccessible(true);
String[] paths = (String[]) userPathsField.get(null);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < paths.length; i++) {
if (libraryPath.equals(paths[i])) {
continue;
}
sb.append(paths[i]).append(';');
}
sb.append(libraryPath);
//修改java.library.path
System.setProperty("java.library.path", sb.toString());
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
//修改完成后重新将sys_paths置为null
sysPathsField.set(null, null);
}
方法还是很简单,利用java的反射机制去设置java.library.path,设置完成之后需要将sys_paths属性置为null。原因见下面的代码,因为sys_paths为null的时候会去加载一次变量,也就是说JVM启动后就不可能再去加载变量,类在加载的时候jvm就启动了,这个时候再去修改变量是不会生效的。
jdk的源码实现:
if (sys_paths == null) {
usr_paths = initializePath("java.library.path");
sys_paths = initializePath("sun.boot.library.path");
}
欢迎大家添加博主微信,备注“技术交流”,拉你进技术交流群

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)