What is the problem with the JAVA class loader?

the virtual machine specification specifies the parent delegation mechanism of the classloader, but due to the problem of the runtime package (namespace), there is isolation, as mentioned in the book, but every class load will save a class file, but I run the custom class loader and load the java.lang.String class many times, why there is no cache locally the second time, do I forget to rewrite that method?

related codes

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");
Mar.28,2021

look at your code you read and load the classes yourself, which requires you to cache the loaded classes yourself. Several standard class loaders provided by Java cache classes that have been loaded by them, so if you delegate class loading to these class loaders, caching will be implemented automatically.


generally speaking, classes are loaded only once and do not need to be loaded repeatedly, so there is no cache. You load it again manually here, so you will have the same output twice. I think there is a problem with the sentence "every class load will save a class file". It should be that the loaded class will produce a Class object (rather than a file), which will be maintained in the heap, and this Class object will not act as a cache, and then loading will be overwritten.

Menu