下面是自定義加載器的實現
package com.ggp.jvm;
import java.io.IOException;
import java.io.InputStream;
/**
* @author: ggp
* @Date: 2019/4/24 08:46
* @Description:
*/
public class ClassLoaderTest {
public static void main(String[] args) throws Exception {
ClassLoader myLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String name)throws ClassNotFoundException{
try{
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
/**
* 本類的同路徑下
*/
InputStream is = this.getClass().getResourceAsStream(fileName);
/**
* 如果未找到class文件,就調用父類的loadClass();
*/
if(is == null){
System.out.println("********super加載***********");
return super.loadClass(name);
}
System.out.println("********this加載***********");
byte[] b = new byte[is.available()];
is.read(b);
/**
* 生成class對象
*/
return defineClass(name,b,0,b.length);
}catch(IOException e){
throw new ClassNotFoundException(name);
}
}
};
myLoader.loadClass("com.ggp.jvm.ClassLoaderTest");
}
}
打印結果
********this加載***********
********super加載***********
按理來說應該只加載一次纔對
我打了斷點追了了代碼,一直到
通過native可以判斷這是個本地方法。然後就又再次調用了loadClass()這個方法
第一次正確加載com.ggp.jvm.ClassLoaderTest這個類
但是加載完成後又再次調用了這個類加載器,並且加載的是java.lang.object這個類
想到java.lang.object是所有類的父類,猜想會不會是類加載的時候也把他的父類加載了
更改代碼驗證猜想
package com.ggp.jvm;
import java.io.IOException;
import java.io.InputStream;
/**
* @author: ggp
* @Date: 2019/4/24 08:46
* @Description:
*/
public class ClassLoaderTest {
public static void main(String[] args) throws Exception {
ClassLoader myLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String name)throws ClassNotFoundException{
try{
System.out.println(name);
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
/**
* 本類的同路徑下
*/
InputStream is = this.getClass().getResourceAsStream(fileName);
/**
* 如果未找到class文件,就調用父類的loadClass();
*/
if(is == null){
System.out.println("********super加載***********");
return super.loadClass(name);
}
System.out.println("********this加載***********");
byte[] b = new byte[is.available()];
is.read(b);
/**
* 生成class對象
*/
return defineClass(name,b,0,b.length);
}catch(IOException e){
throw new ClassNotFoundException(name);
}
}
};
myLoader.loadClass("com.ggp.jvm.Son");
}
}
打印結果
com.ggp.jvm.Son
********this加載***********
com.ggp.jvm.Dad
********this加載***********
java.lang.Object
********super加載***********
Process finished with exit code 0
猜想正確
說明類加載器會通過 defineclass1這個本地方法加載父類