虚拟机规范规定了类加载器的父委托机制,但是由于运行时包(命名空间)的问题,存在隔离,书中提到,但凡是经过的类加载都会保存一份class文件,但是我运行自定义类加载器,多次加载java.lang.String
类,为什么第二次没有在本地没有缓存,是忘记需要重写那个方法吗?

相关代码
public class MyClassLoader extends ClassLoader {
private static Path classDir = Paths.get("/Users/echo/");
public MyClassLoader() {
super();
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classBytes = readClassBytes(name);
if (null == classBytes || classBytes.length == 0) {
throw new ClassNotFoundException("can not load the class " + name + ".");
}
return defineClass(name, classBytes, 0, classBytes.length);
}
private byte[] readClassBytes(String name) throws ClassNotFoundException {
String classPath = name.replace(".", File.separator);
Path classFullPath = classDir.resolve(Paths.get(classPath + ".class"));
if (!classFullPath.toFile().exists()) {
throw new ClassNotFoundException("the class " + name + " not found.");
}
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
Files.copy(classFullPath, bos);
return bos.toByteArray();
} catch (IOException e) {
throw new ClassNotFoundException("load the class " + name + " occur error.", e);
}
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
Class<?> c = findLoadedClass(name);
if (c != null) {
System.out.println("在自定义加载器缓存中找到.");
}
if (c == null) {
long t0 = System.nanoTime();
try {
if (getParent() != null) {
c = getParent().loadClass(name);
if (c != null) {
System.out.println("在父类加载器中找到.");
}
} else {
c = getSystemClassLoader().loadClass(name);
if (c != null) {
System.out.println("直接在根加载器中找到.");
}
}
} catch (ClassNotFoundException e) {
}
if (c == null) {
long t1 = System.nanoTime();
c = findClass(name);
if (c != null) {
System.out.println("在自定义加载器中找到.");
}
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
}
MyClassLoader classLoader = new MyClassLoader();
classLoader.loadClass("java.lang.String");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
classLoader.loadClass("java.lang.String");
看你的代码你是自己读取并加载了类的,这种情况需要你自己缓存已加载的类。Java提供的几个标准类加载器都对经过其加载的类做了缓存,所以如果你把类加载委托给这些类加载器的话是会自动实现缓存的。