我在通过一个如下自定义类加载器的对象第一次加载一个类时,发现它在loadclass指定类后,还会再loadclass java.lang.Object类,我就感到非常疑惑,java.lang.Object类不是应该早就加载在jvm中了吗?并且我用这个自定义类加载器对象第二次加载类时,就不会再loadclass java.lang.Object类了,难道是对于每个加载器对象,都有一个结构来记录经过它loadclass的类吗,而不仅仅是像DIctionary结构一样只记录完全是由它加载的类。在jvm底层到底是如何查询判断一个类是否已经加载的呢?
public static class HotClassLoader extends ClassLoader{
public final static String classFilePath = "D:\\DownLoadProject\\LearnJVM\\out\\production\\LearnJVM\\"; //编译后classpath路径
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
/**
* 重写loadClass方法,拦截指定类 不委托给父类加载器处理
*/
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
//注意:loadClass也会加载name类中引用到的相关的类,例如其父类Object,而Object类需要委托加载,故这里要加个判断
if (name.startsWith("com.hotClass")) {
synchronized (getClassLoadingLock(name)) {
//findLoadedClass:若存在name相同并且加载器实例对象相同的类对象 则将其返回,否则返回null
Class<?> c = findLoadedClass(name);
if (c == null) {
c = findClass(name);
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
return super.loadClass(name, resolve);
}
@Override
protected Class<?> findClass(String classCompleteName) throws ClassNotFoundException {
System.out.println("HotClassLoader尝试加载"+classCompleteName);
byte[] result = getClassFromCustomPath(classFilePath +classCompleteName.replace(".", File.separator)+".class");
if (result == null) {
throw new ClassNotFoundException(classCompleteName);
} else {
return defineClass(classCompleteName, result, 0, result.length);
}
}
private byte[] getClassFromCustomPath(String classFilePath) {
File f = new File(classFilePath);
InputStream is = null;
try {
//读取编译后的文件
is = new FileInputStream(f);
byte[] bytes=new byte[is.available()];
is.read(bytes);
return bytes;
} catch (Exception e){
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}