项目目前需要加载几个外部的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");
}
欢迎大家添加博主微信,备注“技术交流”,拉你进技术交流群