загрузчик классов расширяется от URLClassLoader NoClassDefFoundError

#java #classloader

Вопрос:

Я пытаюсь написать свой собственный загрузчик классов. Вот мой код загрузчика классов.

 package server;

import java.net.URL;
import java.net.URLClassLoader;

public class MyClassloader extends URLClassLoader {

    public MyClassloader(URL[] urls) {
        super(urls);
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        Class<?> aClass = super.findClass(name);

        if (aClass == null) {
            return this.getParent().loadClass(name);
        }

        return aClass;
    }
}

 

И в качестве тестового класса для загрузки есть пустой класс.

 package server;

public class MyClass {}

 

И главная точка входа-это

 package server;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

public class Main {
    public static void main(String[] args) throws Exception {
        
        // the dir that the compiled class file located in.
        File file = new File("/Users/mrd2242/Desktop/javatest/testedClass/");

        MyClassloader myClassloader = new MyClassloader(new URL[]{file.toURI().toURL()});
        Class<?> myClass = myClassloader.loadClass("server.MyClass");

    }
}

 

Как показали комментарии выше, сначала я скомпилирую MyClass MyClass.class . Затем я перемещаю его в каталог /Users/mrd2242/Desktop/javatest/testedClass/ (обратите внимание, что у этого класса есть имя пакета, поэтому абсолютный путь к файлу .class /Users/mrd2242/Desktop/javatest/testedClass/server/MyClass.class равен.), а затем передаю URL-адрес этого каталога конструктору MyClassloader .

Запустите код, но он не удался. Исключением является

 Exception in thread "main" java.lang.NoClassDefFoundError: java/lang/Object
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
    at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:550)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
    at server.MyClassloader.loadClass(MyClassloader.java:14)
    at server.Main.main(Main.java:12)
Caused by: java.lang.ClassNotFoundException: java.lang.Object
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
    at server.MyClassloader.loadClass(MyClassloader.java:14)
    ... 10 more
 

С моей точки зрения, это так запутанно. Я переопределяю этот loadClass метод, чтобы

  1. Первый класс загрузки с заданного URL URLClassLoader -адреса с использованием findClass метода.
  2. Если 1 не удалось, используйте метод родительского загрузчика loadClass классов для выполнения обычного процесса загрузки класса.

Но исключением кажется отчет, который java/lang/Object не найден. Что случилось? Спасибо!

Ответ №1:

 public class MyClassloader extends URLClassLoader {

    public MyClassloader(URL[] urls) {
        super(urls);
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        try {
            Class<?> aClass = super.findClass(name);
            return aClass;
        } catch (Exception e) {
            return this.getParent().loadClass(name);
        }
    }
}
 

Я перемещаю логику отказа в блок «Попытка». Это правильно?