ОБНОВЛЕНИЕ. Все файлы в моем проекте теперь объявляют один и тот же пакет. Однако загружаемая банка должна быть вне пути к классам. Я пробовал child.loadClass(className)
и Class.forName(className, false, child);
, но ни один из них не смог его найти.
Я пишу программу, которая хочет использовать плагины или модули в виде банок и использовать их так, как если бы они были встроены в путь к классам.
Я видел много подобных вопросов здесь и на других сайтах, поэтому прошу прощения за дублирование. Но до сих пор каждый ответ, который я видел, не работал. Я делаю что-то неправильно?
У меня есть папка, полная банок. Я знаю, что у каждой банки есть один класс верхнего уровня, который расширяет класс моего модуля. Но я не знаю, как называются эти классы.
Сначала я нахожу все файлы в каталоге. Это прекрасно работает. Затем для каждого файла я пытаюсь получить экземпляр его класса верхнего уровня, используя следующий код:
(Сначала он открывает банку в виде zip-архива, чтобы получить имена всех классов, затем смотрит на имя, чтобы определить, является ли это классом верхнего уровня, а затем, если это так, он должен загрузить, создать экземпляр и вернуть его.)
private static Module jarLoader(String jar){
try{
ZipInputStream zip = new ZipInputStream(new FileInputStream(ModulesDir+"/"+jar));
URL[] myJarFile = new URL[]{new URL("jar","","file:"+ModulesDir)};
URLClassLoader child = new URLClassLoader (myJarFile , Main.class.getClassLoader());
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
// This ZipEntry represents a class. Now, what class does it represent?
String className = entry.getName().replace('/', '.'); // including ".class"
className = className.substring(0, className.length() - ".class".length());
String[] classNameParts = className.replace('$', ':').split(":");//I don't know why i have to do this, but it won't split on "$"
if(classNameParts.length == 1){
System.out.println("trying to load "+className);
Class classToLoad = Class.forName(className, false, child);
System.out.println("loaded class "+classToLoad.getName());
if(classToLoad.getSuperclass() == Module.class){
Module instance = (Module) classToLoad.newInstance();
return instance;
}
}
}
}
zip.close();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
Он доходит до «попытки загрузить ...» и показывает имя класса, как я и ожидал, а затем выдает java.lang.ClassNotFoundException
.
Использование того же имени для загрузки класса работало нормально, когда я поместил его в файл .java в исходном каталоге, но он не получит его из банки.
Я делаю что-то неправильно? Я подозреваю, что имени класса может понадобиться какой-то префикс или суффикс, но я не могу понять, что именно.
Спасибо за помощь!