Я пытаюсь создать собственный загрузчик классов, чтобы выполнить следующее:
У меня есть класс в пакете com.company.MyClass
Когда загрузчику классов предлагается загрузить что-либо в следующем формате:
com.company.[additionalPart].MyClass
Я бы хотел, чтобы загрузчик классов загружал com.company.MyClass, эффективно игнорируя [additionalPart] имени пакета.
Вот код, который у меня есть:
public class MyClassLoader extends ClassLoader {
private String packageName = "com.company.";
final private String myClass = "MyClass";
public MyClassLoader(ClassLoader parent) {
super(parent);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> clazz = null;
String className = name;
// Check if the class name to load is of the format "com.company.[something].MyClass
if (name.startsWith(packageName)) {
String restOfClass = className.substring(packageName.length());
// Check if there is some additional part to the package name
int index = restOfClass.indexOf('.');
if (index != -1) {
restOfClass = restOfClass.substring(index + 1);
//finally, check if the class name equals MyClass
if (restOfClass.equals(myClass)) {
// load com.company.MyClass instead of com.company.[something].MyClass
className = packageName + myClass;
clazz = super.loadClass(className, true);
}
}
}
if (clazz == null) {
// Normal clase: just let the parent class loader load the class as usual
clazz = super.loadClass(name);
}
return clazz;
}
}
И вот мой тестовый код:
public class TestClassLoader {
public void testClassLoader () throws Exception {
ClassLoader loader = new MyClassLoader(this.getClass().getClassLoader());
clazz = Class.forName("com.company.something.MyClass", true, loader );
}
public static void main (String[] args) throws Exception {
TestClassLoader tcl = new TestClassLoader();
tcl.testClassLoader();
}
}
MyClassLoader подбирает правильный класс (т.е. com.company.MyClass) и корректно возвращает его из loadClass (я прошел через код), однако в какой-то более поздний момент (т.е. после вызова loadClass из JVM) он выдает исключение следующим образом:
Исключение в потоке «основной» java.lang.ClassNotFoundException: com/company/something/MyClass в java.lang.Class.forName0 (собственный метод)
в java.lang.Class.forName(Class.java:247) в [мой код]
Теперь я понимаю, что некоторые из вас могут подумать: «Зачем кому-то это нужно делать? Должен быть лучший способ». Я уверен, что есть, но для меня это что-то образовательное, так как я хотел бы понять, как работают загрузчики классов, и получить более глубокое понимание процесса загрузки классов jvm. Так что, если вы сможете не обращать внимания на бессмысленность процедуры и пошутить надо мной, я буду вам очень признателен.