使用自定义 Java 代理 jar 启动 Spring boot 项目会出现错误

问题描述 投票:0回答:1

如下图,JVM选项中添加自定义Java代理包

-javaagent:/usr/local/maven/apache-maven-3.6.3/repository/com/graviton/Probe-Agent/1.0-SNAPSHOT/Probe-Agent-1.0-SNAPSHOT.jar

定制了一个名为Probe-Agent的jar,用于输出Spring boot应用程序中方法的日志。具体来说,它会输出带有自定义注解

LogAdvice
的方法的日志,如下所示

@RestController
public class HelloController {
    @GetMapping("/hello")
    @LogAdvice
    public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
        return String.format("Hello %s!", name);
    }
}
@SpringBootApplication
@RestController
public class SpringBootProbeApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootProbeApplication.class, args);
    }


}

Probe-Agent jar 中的关键方法如下所示

public class ProbeAgent {

    public static void premain(String agentArgs, Instrumentation inst) {

        System.out.printf("filter class start: %d\n", System.currentTimeMillis());
        LogAdviceTransformer logAdviceTransformer = new LogAdviceTransformer();
        inst.addTransformer(logAdviceTransformer, true);
        System.out.printf("filter class end: %d\n", System.currentTimeMillis());
    }
}

但是,当我启动Springboot应用程序时,出现错误

ERROR o.s.boot.SpringApplication -- Application run failed
org.springframework.beans.factory.BeanDefinitionStoreException: Could not enhance configuration class [com.graviton.springboot.probe.SpringBootProbeApplication]. Consider declaring @Configuration(proxyBeanMethods=false) without inter-bean references between @Bean methods on the configuration class, avoiding the need for CGLIB enhancement.
    at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:120)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:534)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:311)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:363)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:153)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:788)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:606)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
    at com.graviton.springboot.probe.SpringBootProbeApplication.main(SpringBootProbeApplication.java:12)
Caused by: org.springframework.cglib.core.ReflectUtils$2: No compatible defineClass mechanism detected: JVM should be started with --add-opens=java.base/java.lang=ALL-UNNAMED for ClassLoader.defineClass to be accessible. On the module path, you may not be able to define this CGLIB-generated class at all.
    at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:547)
    at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:371)
    at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:575)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(AbstractClassGenerator.java:107)
    at org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(LoadingCache.java:52)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:57)
    at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:130)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:317)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:562)
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:407)
    at org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(ConfigurationClassEnhancer.java:147)
    at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:112)
    ... 13 common frames omitted
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @5f058f00
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
    at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
    at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
    at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:505)
    ... 26 common frames omitted

该错误似乎与 CGLIB 有关,它与 Probe-Agent 一样使用 ASM。

java spring-boot java-bytecode-asm javaagents
1个回答
0
投票

经过一些调查,似乎与此问题类似的问题与 Spring 中的一个旧错误有关。

如果您还没有尝试过,您可以尝试这些建议并重新确认您的 spring 版本,如 org.springframework.cglib.core.ReflectUtils$1 的非法反射访问

中所述
© www.soinside.com 2019 - 2024. All rights reserved.