Получил исключение classnotfoundexception при использовании ClassLoader.getSystemClassLoader()

#java #classloader

#java #classloader

Вопрос:

В tomcat я загружаю HelloWorld, используя загрузчик классов.

   sb.append("package XXXX.XXXXX.XXXX.freemarkerjob;n");
        sb.append("import XXXX.XXXXX.XXXX.freemarkerjob.DoStuff;n");
        sb.append("public class HelloWorld implements DoStuff {n");
        sb.append("    public void doStuff() {n");
        sb.append("        System.out.println("Hello world");n");
        sb.append("    }n");
        sb.append("}n");


Class<?> helloClass = InMemoryJavaCompiler.compile("XXXX.XXXXX.XXXX.HelloWorld", sb.toString(), optionList);
  

И я обнаружил, что если я использую Thread.currentThread().getContextClassLoader() в качестве родительского элемента DynamicClassLoader, то я могу успешно загрузить класс, однако, если я использую (ClassLoader.getSystemClassLoader() , это вызовет исключение classnotfoundexception при вызове метода cl.loadClass(className); , которому не удалось загрузить интерфейс doStuff , в котором HelloWorld его реализует.
что мне нужно знать, почему SystemClassLoader не может загрузить интерфейс?

 DynamicClassLoader cl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());


DynamicClassLoader cl = new DynamicClassLoader(ClassLoader.getSystemClassLoader());


    Class<?> helloClass = InMemoryJavaCompiler.compile("XXXX.XXXXX.XXXX.HelloWorld", sb.toString(), optionList);



public static Class<?> compile(String className, String sourceCodeInText, Iterable<String> options) throws Exception {

This one successfully 
         DynamicClassLoader cl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());

This one failed
        //     DynamicClassLoader cl = new DynamicClassLoader(ClassLoader.getSystemClassLoader());

 cl.loadClass(className);

}

package XXXX.XXXXX.XXXX.dynamicjava;
import java.util.HashMap;
import java.util.Map;
public class DynamicClassLoader extends ClassLoader {
    private Map<String, CompiledCode> customCompiledCode = new HashMap<>();
    public DynamicClassLoader(ClassLoader parent) {
        super(parent);
    }
    public void setCode(CompiledCode cc) {
        customCompiledCode.put(cc.getName(), cc);
    }
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        CompiledCode cc = customCompiledCode.get(name);
        if (cc == null) {
          Class<?> curClass = super.findClass(name);
            if (curClass == null) {
                return null;
            } else {
                return curClass;
            }
        }
        byte[] byteCode = cc.getByteCode();
        return defineClass(name, byteCode, 0, byteCode.length);
    }
}
  

Ответ №1:

Ваш интерфейс (doStuff) не загружается SystemClassLoader, обычно он загружается загрузчиками классов приложений.

Если вы хотите сделать HelloWorld доступным в контексте doStuff, используйте следующее,

DynamicClassLoader cl = новый DynamicClassLoader(doStuff.class.getClassLoader());