参考的相关资料如下:
1、java 动态库卸载_java 卸载动态链接库 - 全栈程序员必看 (javaforall.cn)
2、java的类加载器以及如何自定义类加载器_磊哥 低调的博客-CSDN博客
3、Java 避免多次动态链接库(dll或.so)_风知前的博客-CSDN博客
4、java - 如何获取已加载的 JNI 库列表?- 堆栈溢出 (stackoverflow.com)
思路如下:
加载dll的时候定义一个变量,在同一个jvm里,别的classloader使用system.load加载前,判断一下这个变量的值。第二次加载的时候,把加载的 dll 删除,然后再重新加载,就不会有重复加载的问题了。
目前还有一个问题是获取到加载的该dll 的classloader,还没找到办法 T-T
代码如下
package test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Vector;
import java.util.concurrent.TimeUnit;
public class TestCall {
public static final String CHR = null;
public static void main(String[] args) {
try {
int a = 0;
String jPath = System.getProperty("java.class.path");
System.out.println(jPath);
String path = "C:\\D\\work\\JNI\\";
jPath += ";" + path + "test.class";
System.setProperty("java.class.path", jPath);
// System.load("C:\\D\\work\\JNI\\MyLog.dll");
MyClassLoader myClassLoader = new MyClassLoader();
myClassLoader.setPath(path);
Class<?> myLog = myClassLoader.loadClass("test");
System.out.println(myLog.getClassLoader());
MyClassLoader myClassLoader1 = new MyClassLoader();
myClassLoader1.setPath(path);
Class<?> myLog1 = myClassLoader1.loadClass("test");
System.out.println(myLog1.getClassLoader());
Object o = myLog.newInstance();
System.out.println("o run " + o.getClass().getClassLoader());
// Method m1 = o.getClass().getMethod("show", null);
// m1.invoke(new Object(), null);
new TestCall().freeDll("MyLog.dll", myClassLoader);
new TestCall().freeDll("MyLog", myClassLoader);
System.setProperty("mylog","false");
delay(4);
Object o1 = myLog1.newInstance();
System.out.println("o1 run " + o1.getClass().getClassLoader());
System.out.println(TestCall.a);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void delay(int second) throws InterruptedException {
for (int i = 1; i <= second; i++) {
System.out.println(i);
TimeUnit.SECONDS.sleep(second);
}
}
public static int a = getA();
public static int getA() {
return 10;
}
public synchronized void freeDll(String dllName, ClassLoader classLoader) {
try {
// ClassLoader classLoader = this.getClass().getClassLoader();
Field field = ClassLoader.class.getDeclaredField("nativeLibraries");
field.setAccessible(true);
Vector libs = (Vector) field.get(classLoader);
Iterator it = libs.iterator();
Object o;
while (it.hasNext()) {
o = it.next();
Field[] fs = o.getClass().getDeclaredFields();
boolean hasInit = false;
for (int k = 0; k < fs.length; k++) {
if (fs[k].getName().equals("name")) {
fs[k].setAccessible(true);
String dllPath = fs[k].get(o).toString();
if (dllPath.endsWith(dllName)) {
hasInit = true;
}
}
}
if (hasInit) {
Method finalize = o.getClass().getDeclaredMethod("finalize", new Class[0]);
finalize.setAccessible(true);
finalize.invoke(o, new Object[0]);
it.remove();
libs.remove(o);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}