Я пытаюсь загрузить класс из JAR, представленного как массив byte [] во время выполнения.
Я знаю две вещи класса нагрузки:
1. он реализует «RequiredInterface»
2. Я знаю, что это квалифицированное имя: «sample.TestJarLoadingClass»
Я нашел solution, в котором я должен продлить ClassLoader но он выбрасывает:ClassNotFoundException при попытке загрузить класс из внешнего JAR во время выполнения
Exception in thread "main" java.lang.ClassNotFoundException: sample.TestJarLoadingClass
at java.lang.ClassLoader.findClass(ClassLoader.java:530)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at tasks.Main.main(Main.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
всякий раз, когда я хочу загрузить класс.
Что может быть причиной этой ситуации и как я могу избавиться от этого?
Любая помощь высоко оценили
Основной метод:
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
Path path = Paths.get("src/main/java/tasks/sample.jar");
RequiredInterface requiredInterface = (RequiredInterface) Class.forName("sample.TestJarLoadingClass", true, new ByteClassLoader(Files.readAllBytes(path))).newInstance();
}
Пользовательский класс погрузчик:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ByteClassLoader extends ClassLoader {
private final byte[] jarBytes;
private final Set<String> names;
public ByteClassLoader(byte[] jarBytes) throws IOException {
this.jarBytes = jarBytes;
this.names = loadNames(jarBytes);
}
private Set<String> loadNames(byte[] jarBytes) throws IOException {
Set<String> set = new HashSet<>();
try (ZipInputStream jis = new ZipInputStream(new ByteArrayInputStream(jarBytes))) {
ZipEntry entry;
while ((entry = jis.getNextEntry()) != null) {
set.add(entry.getName());
}
}
return Collections.unmodifiableSet(set);
}
@Override
public InputStream getResourceAsStream(String resourceName) {
if (!names.contains(resourceName)) {
return null;
}
boolean found = false;
ZipInputStream zipInputStream = null;
try {
zipInputStream = new ZipInputStream(new ByteArrayInputStream(jarBytes));
ZipEntry entry;
while ((entry = zipInputStream.getNextEntry()) != null) {
if (entry.getName().equals(resourceName)) {
found = true;
return zipInputStream;
}
}
} catch (IOException e) {;
e.printStackTrace();
} finally {
if (zipInputStream != null && !found) {
try {
zipInputStream.close();
} catch (IOException e) {;
e.printStackTrace();
}
}
}
return null;
}
}
RequiredInterface:
public interface RequiredInterface {
String method();
}
класс в JAR-файле:
package sample;
public class TestJarLoadingClass implements RequiredInterface {
@Override
public String method() {
return "works!";
}
}
Я использовал код, который вы разместили на моей машине, и все сработало. Не могли бы вы опубликовать точное исключение? Также проверьте, действительно ли путь, который вы используете, **, ** указывает на банку, которая содержит класс, который вы хотите загрузить? –
Хорошо, я отправил все сообщение об исключении. Я проверил все возможные «глупые» ошибки, все должно работать. Убедитесь, что у вас нет класса, требуемого для загрузки в диапазоне вашего загрузчика классов. –
Да, вы правы, по ошибке я добавил зависимость от jar с классом вместо jar с интерфейсом. Извините –