Размышления - Java 8 - неверный тип константы
У меня проблема с библиотекой Reflections. Я пытаюсь динамически загружать все классы, которые реализуют определенный интерфейс. Все работает нормально (все классы загружены), пока я не использую лямбда-выражения в этих классах (Java 8). Я попытался обновить версию lib, но эффект был таким же (java.io.IOException: недопустимый тип константы: 18).
Зависимость и встроить в pom.xml
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
<exclusions>
<exclusion>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.19.0-GA</version>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
без исключения тот же эффект.
Код:
URL jarUrl = jarFile.toURI().toURL();
URLClassLoader child = new URLClassLoader(new URL[]{jarUrl}, this.getClass().getClassLoader());
ConfigurationBuilder builder = new ConfigurationBuilder()
.addClassLoader(child)
.addUrls(jarUrl)
.setScanners(new SubTypesScanner());
Reflections r = new Reflections(builder);
return r.getSubTypesOf(cls);
Как я могу загрузить классы с лямбда-выражением?
PS извините за английский:)
5 ответов
Если вы посмотрите на эту таблицу, вы увидите, что "константный тип: 18" относится к CONSTANT_InvokeDynamic
атрибут, значение тега которого 18
,
Таким образом, вы используете библиотеку, которая имеет анализатор классов, который не совместим с Java 8. На самом деле, этот синтаксический анализатор класса даже не совместим с Java 7, так как это постоянное значение указывается начиная с Java 7. Ему просто это сошло с рук, поскольку обычный код Java не использует эту функцию в Java 7. Но при взаимодействии с кодом, созданным другими языки программирования для JVM, это может даже потерпеть неудачу с Java 7.
В трекере ошибок в Reflections есть элемент, описывающий вашу проблему. Внизу вы найдете уведомление:
С этим исправлением: https://issues.jboss.org/browse/JASSIST-174 javassist получил поддержку этой константы. Так что с 3.18.2-GA эта ошибка не возникает.
Я решил эту проблему, что;
Первое обновление javassist
баночка для -> 3.18.2-GA
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.2-GA</version>
</dependency>
Во-вторых добавьте weblogic.xml
<wls:package-name>javassist.*</wls:package-name>
Я только что исправил подобную проблему здесь. В моем случае на моем пути к классу было два баночки с javassist. Я использую Maven, и это должно было избежать этого, но одна из зависимостей использовала другой идентификатор группы (javassist
для старого и org.javassist
для нового, импортированного org.reflections
), поэтому Maven рассматривал их как разные артефакты.
Я просто изменил библиотеку в зависимости от старой, чтобы она зависела от новой, и все исправлено!
В Websphere я решил эту проблему, включив загрузчик классов "родительский последний" для этого приложения, чтобы JAR-файлы, поставляемые с приложением, имели приоритет над теми, которые предоставляет сервер.
Если вы используете weblogic, это может привести к конфликту с библиотеками, уже загруженными его загрузчиком классов. Вы можете переопределить их, поставив
...
<weblogic-web-app>
<container-descriptor>
<prefer-application-packages>
<package-name>javassist.*</package-name>
...
в ваших веб-проектах weblogic.xml
Конфигурационный файл Обратите внимание, что настоящий пакет Java просто javassist
не org.javassist
(Maven GroupId).
У меня была эта проблема, поэтому я временно выполнил понижение с моего jdk, EXPORT JAVA_HOME="/home/user/jdk1.7.0_55" и все работало нормально.