Неверный тип в пуле констант после горячей замены кода с использованием DCEVM
Привет всем! Для контекста я работаю над простым весенним проектом в intelliJ, чтобы сконфигурировать его с HotswapAgent с использованием DCEVM [8u181 build 2 ] вместе с совместимым JDK [ 8u181 ] на сервере приложений Payara 5.0.
Пожалуйста, согласитесь со мной в следующих нескольких фрагментах кода и моем правдоподобном объяснении того, что происходит, и это не вопрос синтаксиса Spring MVC, или он работает.
Это пример кода, который я тестирую на Hotswapping [Не на встроенной JVM, но с использованием DCEVM ] и HotswapAgent [1.3.0]
HelloWorldController.java
@Controller
public class HelloWorldController {
@Autowired HelloService helloService;
@RequestMapping("/hello")
public String hello(
@RequestParam(value = "name", required = false, defaultValue = "World") String name,
Model model) {
model.addAttribute("name", name);
System.out.println( helloService.sayHello() );
return "helloworld";
}
Я не хочу включать код для helloService, так как это может раздуть этот пост.
HelloService.sayHello () просто печатает наиболее важный Hello World в консоли
Как вы можете видеть выше, автоматическое подключение включено, и оно выполняет правильную функцию (сказано выше).
После этого я закомментирую аннотацию Autowired и вызов функции, и это дает мне ошибку, которая:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.annotation.AnnotationFormatError: java.lang.IllegalArgumentException: Wrong type at constant pool index
Сконцентрируйся:
java.lang.IllegalArgumentException: Wrong type at constant pool index
Я отладил приложение и обнаружил, что IllegalArgumentException возникла, когда AnnotationParser анализировал аннотации класса Spring Controller из пула констант, а члены (одной из аннотаций, которая является "типом" аннотации), были неправильными, когда она был взят из константного пула класса.
Таким образом, насколько мне известно, горячее развертывание выполняется неправильно (хотя HotswapAgent говорит, что он перезагрузил класс на сервере Payara) или что-то не так с коммуникацией JVM или JDK, и я говорю это, потому что, когда я делаю обратное, это закомментирование автопроводки, затем горячее развертывание и запуск, поэтому я получаю исключение нулевого указателя.
Примечание: только для дополнительной информации
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
Если кому-то понадобится дополнительная информация, код или информация об этом, я буду более чем рад уточнить. Спасибо за ваше время всем.
2 ответа
Ну, это было странно решить, но это не связано с версией JDK или DCEVM, а связано с сервлетом-диспетчером Spring.
Мой сервлет-диспетчер пропал без вести:
<annotation-driven />
Именно поэтому он не мог зарегистрировать класс контроллера и вызвал нежелательное поведение. Также отсутствовали добавленные XML-схемы.
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
Просто для целей завершения или, если это кому-нибудь пригодится, я выложу полную конфигурацию сервлет-диспетчера.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<annotation-driven />
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.test" />
</beans:beans>
Политика хранения Autowire является @Retention(RetentionPolicy.RUNTIME).
Согласно спецификации JVM, аннотация должна быть доступна в двоичном виде. (Ссылка: https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html)
Я предполагаю, что java сохраняет ссылку в постоянном пуле всех классов с аннотацией RUNTIME. При его горячей замене класс заменяется в "горячем" режиме, но постоянный пул не обновляется, чтобы отразить перестановку классов.
Существует аналогичная открытая проблема с hotswapagent: https://github.com/HotswapProjects/HotswapAgent/issues/256