我正在尝试制作一个java代理来转储方法的调用者。我正在使用 objectweb 的 ASM 来转换目标方法以调用转储调用者和目标方法的内部状态的函数。
代理是在 Java 11.0.20 下编译的(如果重要的话可以使用 gradle)。它是通过 -javaagent 命令标志运行的。 ASM版本是9.6。
目标jar是Bukkit-1.8.8,在Java 8下编译。但是,我在java 17下运行bukkit jar,因此JVM理解代理jar应该没有问题。
完整日志:
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
预期结果:代理将转储写入转储文件。 实际结果:整个事情崩溃并烧毁。
这不是https://stackoverflow.com/a/72229157/139985的重复,因为我的ASM版本已更新并且可以处理jdk17和jdk8。
您遇到的错误通常是由于用于编译类的 Java 版本与用于运行它们的版本不匹配而发生的。:
首先,验证系统上安装的 Java 版本。运行以下命令检查版本: java -版本
确保显示的版本与用于编译代码的 Java 版本兼容。如果不匹配,您可能需要使用正确的版本重新编译您的类。
编译时可以使用javac命令指定源版本和目标版本。例如,要使用 Java 11 进行编译,请使用: javac -source 11 -target 11 YourClass.java
这将确保源代码和生成的字节码都与 Java 11 兼容。