大多数情况下,jar 文件的冲突 maven,gradle 等依赖管理都能自动处理。但是,一些情况下,这些工具也显得无能为力。
假设foo.jar 1.0与2.0 不能完全兼容,项目需要使用一个第三方的sdk依赖 foo.jar 1.0 ,但是项目原有的代码又依赖foo.jar 2.0, 这时候,如果使用1.0 或者2.0 都是不行的。
我们知道,Java中的类的唯一标志是 类加载器+ 类的全限定名,那么我们只需要把foo.jar 1.0 让自定义的类加载器去加载,这样foo.jar 1.0中的
package demo;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class UnconventionalClassLoader extends ClassLoader {
private Map<String,byte[]> clazz;
public UnconventionalClassLoader(String ...files) throws IOException {
clazz=new HashMap<>();
for (String file : files) {
JarFile jarFile = new JarFile(file);
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()){
JarEntry jarEntry = entries.nextElement();
if(jarEntry.getName().endsWith(".class")){
try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
int pos=0;
int len;
byte[] buff=new byte[inputStream.available()];
while ((len=inputStream.read(buff,pos,buff.length-pos))>0){
pos+=len;
}
String className=jarEntry.getName().replace("/",".")
.replace(".class","");
clazz.put(className,buff);
}
}
}
}
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
Class<?> cz = findLoadedClass(name);
if(cz==null){
byte[] bytes = clazz.get(name);
if(bytes==null){
cz=super.loadClass(name,resolve);
}else{
cz=defineClass(name,bytes,0,bytes.length);
}
}
return cz;
}
}
//使用方式展示
public static void main(String[] args) throws ClassNotFoundException, IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
UnconventionalClassLoader unconventionalClassLoader = new UnconventionalClassLoader("E:\\commons-codec-1.10.jar");
Class<?> aClass = unconventionalClassLoader.loadClass("org.apache.commons.codec.binary.StringUtils");
System.out.println(aClass.getClassLoader().getClass().getName());
Method equals = aClass.getMethod("equals",CharSequence.class,CharSequence.class);
boolean b= (boolean) equals.invoke(null,"s1","s2");
System.out.println(b);
}
}
网友评论