У меня возникают проблемы с небольшим проектом, над которым я работаю. В этом проекте я пытаюсь динамически создавать классы из конфигурации String и загружать их в JVM.ClassFormatError при определении класса в среде OSGI
Когда я делаю это в «нормальной» среде (Unit Tests), все работает нормально. Но когда я пытаюсь создать классы в среде OSGI (Apache Karaf), я получаю ClassFormatError с сообщением «Недопустимое имя класса» Ljava/lang/String; «в классе ...».
После короткого исследования выяснилось, что эта проблема возникает для классов в java/lang, когда они не загружаются загрузчиком системного класса, но я все остальное, чем эксперт, когда дело доходит до загрузки классов в java и особенно OSGi.
Я думаю, что путь я получаю доступ к методу defineClass
может представлять интерес для этой проблемы, так вот она:
PROTECTION_DOMAIN = (ProtectionDomain) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return RestEndpoint.class.getProtectionDomain();
}
});
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
try {
Class loader = Class.forName("java.lang.ClassLoader");
DEFINE_CLASS = loader.getDeclaredMethod("defineClass",
new Class[]{ String.class,
byte[].class,
Integer.TYPE,
Integer.TYPE,
ProtectionDomain.class });
DEFINE_CLASS.setAccessible(true);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
return null;
}
});
Последняя (надеюсь, полезная) часть информации является ClassLoader Я вызывая метод defineClass при запуске моего проекта в комплекте OSGi: это экземпляр org.apache.felix.framework.BundleWiringImpl.
Было бы здорово, если бы кто-то мог помочь мне здесь!
Привет, Pascal
EDIT: мне нужно определить классы во время выполнения, потому что я хочу, чтобы избежать шаблонный код в моем проекте и сделать программу более последовательной.
Чтобы быть более точным, моим проектом будет RESTful WebService. Поскольку я использую несколько технологий для хранения данных и snychronize процессов (mongoDB, MySQL, activeMQ, ...), я хочу использовать верблюд Apache для работы со всеми различными технологиями. Проблема заключается в том, что я не знаю, насколько хорошо знаю Camel с подходом Java к REST (все сопоставление методов и классов с HTTP-запросами выполняется с помощью аннотаций). Таким образом, единственной возможностью для меня было написать методы, которые будут размещать параметры запроса в заголовках обмена Camel и запускать их по маршруту. Чтобы избежать этого, я хотел автоматизировать этот процесс, определив эти классы во время выполнения из определений маршрутов.
Почему вы пытаетесь определить класс 'java.lang.String'? Конечно, это уже существует и определяется загрузчиком загрузки классов? В Java только загрузчивому загрузчику классов разрешено определять классы, имя которых начинается с 'java.'. –
Можете ли вы немного объяснить, почему вы создаете пользовательские классы? Возможно, есть еще лучший способ добиться того, чего вы хотите в OSGi. –
@NeilBartlett Я не хочу определять java.lang.String. Я хочу определить совершенно новый класс, который, например, входной параметр типа String. Кристиан, я обновил вопрос, чтобы вы могли сделать более точную картину проблемы. – user2764975