You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用Instrumentation#retransformClasses时Java Agent抛出UnsupportedClassVersionError

问题描述

我正在开发一个Java Agent,用于dump方法的调用者:通过ObjectWeb ASM修改目标方法,插入调用记录调用者与方法内部状态的dump函数。相关环境与问题如下:

  • Agent基于Java 11.0.20编译(Gradle构建),通过-javaagent命令参数启动
  • ASM版本为9.6(已确认支持JDK 8与JDK 17)
  • 目标Jar是基于Java 8编译的Bukkit-1.8.8,运行在Java 17环境中
  • 调用Instrumentation#retransformClasses时抛出UnsupportedClassVersionError,导致程序崩溃
  • 预期结果:Agent将dump内容写入文件;实际结果:程序崩溃

完整报错日志:

Exception in thread "main" java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:491)
        at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:503)
Caused by: java.lang.UnsupportedClassVersionError
        at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
        at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:169)
        at me.cire3.sfbf.SFBFAgentEntryPoint.transform(SFBFAgentEntryPoint.java:39)
        at me.cire3.sfbf.SFBFAgentEntryPoint.premain(SFBFAgentEntryPoint.java:17)
        ... 6 more
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message Outstanding error when calling method in invokeJavaAgentMainMethod at s\src\java.instrument\share\native\libinstrument\JPLISAgent.c line: 619
*** java.lang.instrument ASSERTION FAILED ***: "success" with message invokeJavaAgentMainMethod failed at s\src\java.instrument\share\native\libinstrument\JPLISAgent.c line: 459
*** java.lang.instrument ASSERTION FAILED ***: "result" with message agent load/premain call failed at s\src\java.instrument\share\native\libinstrument\JPLISAgent.c line: 422
FATAL ERROR in native method: processing of -javaagent failed, processJavaStart failed

问题分析

核心原因是类文件版本不匹配:

  1. ASM默认会以当前运行JVM的版本(Java 17,版本号61)生成修改后的类文件,但目标类原始版本为Java 8(版本号52),JVM在retransform时检测到版本不一致,抛出UnsupportedClassVersionError。
  2. Agent本身以Java 11编译(版本号55),虽然JVM能加载Agent类,但在retransform操作的版本校验环节触发异常。

解决方案

1. 调整Gradle编译配置,强制Agent兼容Java 8

在build.gradle中设置源兼容性与目标兼容性为Java 8,确保Agent类文件版本为52:

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

若使用模块化项目,需同步调整module-info.java的兼容性声明。

2. ASM修改类时显式复用原始类版本

在ClassFileTransformer的transform方法中,解析原始类的版本号,并传递给ClassWriter,确保修改后的类版本与原始类一致:

@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
    // 仅处理目标类
    if (!className.equals("your/target/class/FullName")) {
        return null;
    }

    ClassReader cr = new ClassReader(classfileBuffer);
    // 获取原始类的版本号(前4字节)
    int originalClassVersion = cr.readInt();
    
    // 使用原始版本创建ClassWriter,保留原有类结构
    ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
    // 自定义ClassVisitor时,确保生成的指令符合Java 8规范
    ClassVisitor cv = new YourCustomClassVisitor(cw, originalClassVersion);
    
    cr.accept(cv, 0);
    return cw.toByteArray();
}

3. 确保retransform配置正确

启动Agent时,需将addTransformer的第二个参数设为true,明确支持retransform操作:

public static void premain(String agentArgs, Instrumentation inst) {
    inst.addTransformer(new YourClassTransformer(), true);
    // 触发retransform
    try {
        inst.retransformClasses(TargetClass.class);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4. 验证类版本

修改完成后,可通过javap -verbose path/to/modified/class.class查看类文件版本,确认版本号为52(对应Java 8)。

内容的提问来源于stack exchange,提问作者a a

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 11:33:23