使用 DCEVM 热交换代码后常量池中的类型错误

Wrong Type at Constant Pool after Hot-Swapping Code using DCEVM

大家好! 对于上下文,我正在 intelliJ 中开发一个简单的 spring 项目,以使用 HotswapAgent using 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 的代码,因为它可能会膨胀post。

HelloService.sayHello() 只是在控制台中生成了典型的 Hello World

正如您在上面看到的那样,自动接线已打开并且它执行正确的功能(如上所述)。

在此之后我注释掉了 Autowired Annotation 和函数调用,这给了我一个错误:

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

我调试了应用程序,发现当 AnnotationParser 从常量池和成员(一个注释的 'type')从 Class 的常量池中取出时不正确。

所以据我所知,热部署没有正确完成(即使 HotswapAgent 说它已经在 Payara 服务器上重新加载了 class)或者 JVM 通信或 JDK,我这样说是因为当我做相反的事情时,先注释掉自动装配,然后热部署,然后 运行,然后我得到一个空指针异常。

注意:仅供补充信息

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException

如果有人需要更多信息或代码或登录,那么我很乐意澄清。谢谢大家的宝贵时间。

A​​utowire 的保留策略是@Retention(RetentionPolicy.RUNTIME)。

根据 JVM 规范,注释应该以二进制形式提供。 (参考:https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.4.2

我的假设是 java 将引用保存在所有带有 RUNTIME 注释的 classes 的常量池中。当你热交换它时,class 被热交换但常量池没有刷新以反映 class 交换。

hotswapagent 有一个类似的未解决问题:https://github.com/HotswapProjects/HotswapAgent/issues/256

这个解决起来很奇怪,但它与 JDK 版本或 DCEVM 无关,而是与 Spring 的调度程序 servlet 相关。

我的 Dispatcher Servlet 丢失了:

<annotation-driven />

这就是它无法注册控制器 class 并导致意外行为的原因。还缺少添加的 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"

为了完成目的或者如果对任何人有帮助,我将 post 完整的调度程序 servlet 配置。

<?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>