昨天面试被问到了加载两个全类名相同的类到jvm,大概的流程我知道但没具体实现过,现在来写一下大致流程
首先可以通过自定义类加载器来加载这两个类,具体如何实现呢,首先继承ClassLoader,重写这个findClass()方法,去我自己定义的路径加载这个类,但由于双亲委派的机制,他是直接交给父类加载了,不会走我写的findClass(),所以应该重写他的loadclass,大致为先执行findClass(),直接加载我定义的类,其他的类加载不了后面再用父类的loadclass加载,实现加载两个全限定名相同的类加载到jvm的效果。
第一个Test_class
package lgy;
public class Test_class {
public void sout(){
System.out.println("调用成功");
}
}
第二个Test_class
package lgy;
public class Test_class {
public void sout(){
System.out.println("调用成功2");
}
}
自定义类加载器
package lgy.ClassLoad;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MyclassLoad extends ClassLoader{
private String classPath;
public MyclassLoad(String classPatn){
this.classPath=classPatn;
}
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
try {
byte[]data = loadBytes(name);
return defineClass(name, data, 0, data.length);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
private byte[] loadBytes(String name) throws IOException {
//要读取类的路径
String path=name.replace('.','/').concat(".class");
//去这个路径下找元素
FileInputStream fileInputStream=new FileInputStream(classPath+ "/"+ path);
int len=fileInputStream.available();//返回还剩的字节数
byte data[]=new byte[len];
fileInputStream.read(data);
fileInputStream.close();
return data;
}
@Override
protected Class> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)){
Class> c = findClass(name);
//为空则直接交给父类加载
if(c==null){
// if(!name.startsWith("lgy")){
c=this.getParent().loadClass(name);
// }else {
// c=findClass(name);
// }
}
if(resolve){
resolveClass(c);
}
return c;
}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
try {
MyclassLoad myclassLoad = new MyclassLoad("D:\");
Class> aClass = myclassLoad.loadClass("lgy.Test_class");
Object o = aClass.newInstance();
Method sout = aClass.getDeclaredMethod("sout", null);
sout.invoke(o, null);
System.out.println(o.getClass());
System.out.println(aClass.getClassLoader().getClass().getName());
MyclassLoad myclassLoad1 = new MyclassLoad("C:\Users\q'q'w\Desktop\新建文件夹\JVM_Test\target\classes");
Class> aClass1 = myclassLoad1.loadClass("lgy.Test_class");
Object o1 = aClass1.newInstance();
Method sout1 = aClass1.getDeclaredMethod("sout", null);
sout1.invoke(o1, null);
System.out.println(o1.getClass());
System.out.println(aClass1.getClassLoader().getClass().getName());
System.out.println(o==o1);
}catch (Exception e){
}
}
}
第一个Test_class提前编译好放到其他的文件夹下即可
异常是加载其他类没加载到不用管,后面会调用父类加载



