一、同一个类文件被不同类加载器加载,它们的Class对象不相等。
执行主类代码如下:
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
/**
* @Author 周利东
* @Date: 2019/1/18 9:47
*/
public class ClassLoaderTest1 extends ClassLoader{
public ClassLoaderTest1(){}
public ClassLoaderTest1(ClassLoader parents){
super(parents);
}
public static byte[] findClassBytes(String name) throws ClassNotFoundException {
String url = "C:\\Users\\周利东\\Desktop\\" + name + ".class";
File file = new File(url);
try(FileInputStream fileInputStream = new FileInputStream(file)){
byte[] bytes = new byte[1024];
int readNum;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
do{
readNum = fileInputStream.read(bytes);
if (readNum<=0) break;
byteArrayOutputStream.write(bytes, 0, readNum);
}while (readNum>0) ;
return byteArrayOutputStream.toByteArray();
}catch (Exception e){
e.printStackTrace();
throw new ClassNotFoundException("没找到文件");
}
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try{
byte[] bytes = findClassBytes(name);
return defineClass(name, bytes , 0, bytes.length);
}catch (Exception e){
e.printStackTrace();
throw new ClassNotFoundException("没找到文件");
}
}
public static void main(String[] args) throws Exception {
ClassLoaderTest1 classLoaderTest1 = new ClassLoaderTest1(ClassLoader.getSystemClassLoader().getParent());
ClassLoaderTest2 classLoaderTest2 = new ClassLoaderTest2(ClassLoader.getSystemClassLoader().getParent());
Class<?> ttttttt1 = Class.forName("TTTTTTT", true, classLoaderTest1);
Class<?> ttttttt2 = Class.forName("TTTTTTT", true, classLoaderTest2);
System.out.println(ttttttt1.equals(ttttttt2));
System.out.println("ttttttt1:classloader--"+ttttttt1.getClassLoader());
System.out.println("ttttttt2:classloader--"+ttttttt2.getClassLoader());
System.out.println(ttttttt1.newInstance().toString());
System.out.println(ttttttt2.newInstance().toString());
}
}
其中涉及到的两个class文件的java代码:(注意,这两个java要编译成class文件放到桌面,上面IO流的路径也可以自己更改)
/**
* @Author 周利东
* @Date: 2019/1/18 16:28
*/
public class TTTTTTT {
private TTTTTTT(){}
@Override
public String toString() {
return "classLoaderName=="+BeCaller.class.getClassLoader().toString()+"|||className=="+BeCaller.class.getName();
}
}
/**
* @Author 周利东
* @Date: 2019/1/18 16:29
*/
public class BeCaller {
private BeCaller(){}
}
做完上面的步骤之后,执行主类,输出结果为:
false
ttttttt1:classloader--ClassLoaderTest1@677327b6
ttttttt2:classloader--ClassLoaderTest2@7f31245a
classLoaderName==ClassLoaderTest1@677327b6|||className==BeCaller
classLoaderName==ClassLoaderTest2@7f31245a|||className==BeCaller
根据上面输出结果:
第一行可知:不同类加载器加载的同一个类的Class对象不相等。
第二、三行可知:ttttttt1和ttttttt2两个class对象 的确是由不同类加载器加载的
第四、五行可知:被TTTTTT类toString方法调用的BeCaller类,也分别由TTTTTT类所属的类加载器进行加载。即,一个类被某个类加载器加载,那么这个类所调用的所有类都会被这个类加载器加载。。
二、自定义类加载器所加载的类中 ,内部又调用了其他类,这些类由什么类加载器加载?
答:如果一个类被某个类加载器加载,那么该类内部调用了其他类的话,这些类默认也是由这个类加载器进行加载。。。除非内部又使用了其他类加载器。