gpt4 book ai didi

java - 无法加载动态生成的字节码

转载 作者:太空宇宙 更新时间:2023-11-04 06:08:52 26 4
gpt4 key购买 nike

我已成功使用 ASM 将动态生成的字节码转储到文件中,但无法加载它。错误信息是:

java.lang.ClassFormatError: JVMCFRE102 field signature invalid; class=TGWD, offset=0
at java.lang.ClassLoader.defineClass(ClassLoader.java:364)
at java.lang.ClassLoader.defineClass(ClassLoader.java:284)
at java.lang.invoke.ByteCodeClassLoader.run(ByteCodeClassLoader.java:20)

BytecodeClassLoader 是我在这里编写的一个类。 javap -v 结果也如下所示。

Classfile /C:/temp/TGWD.class
Last modified Mar 10, 2015; size 750 bytes
MD5 checksum 462ec39a439ab0d30c676eb92a93fd5a
public class TGWD extends java.lang.invoke.BaseTemplate
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER

Constant pool:
#1 = Utf8 TGWD
#2 = Class #1 // TGWD
#3 = Utf8 java/lang/invoke/BaseTemplate
#4 = Class #3 // java/lang/invoke/BaseTemplate
#5 = Utf8 guard
#6 = Utf8 Ljava/lang/invoke/MethodHandle;
#7 = Utf8 trueTarget
#8 = Utf8 falseTarget
#9 = Utf8 <init>
#10 = Utf8 (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V
#11 = Utf8 java.lang.invoke.MethodHandle
#12 = NameAndType #5:#11 // guard:java.lang.invoke.MethodHandle
#13 = Fieldref #2.#12 // TGWD.guard:java.lang.invoke.MethodHandle
#14 = NameAndType #7:#11 // trueTarget:java.lang.invoke.MethodHandle
#15 = Fieldref #2.#14 // TGWD.trueTarget:java.lang.invoke.MethodHandle
#16 = NameAndType #8:#11 // falseTarget:java.lang.invoke.MethodHandle
#17 = Fieldref #2.#16 // TGWD.falseTarget:java.lang.invoke.MethodHandle
#18 = Utf8 eval
#19 = Utf8 ()V
#20 = Utf8 Hello
#21 = Utf8 (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
#22 = Utf8 java/lang/Throwable
#23 = Class #22 // java/lang/Throwable
#24 = NameAndType #5:#6 // guard:Ljava/lang/invoke/MethodHandle;
#25 = Fieldref #2.#24 // TGWD.guard:Ljava/lang/invoke/MethodHandle;
#26 = Utf8 java/lang/invoke/MethodHandle
#27 = Class #26 // java/lang/invoke/MethodHandle
#28 = Utf8 invokeExact
#29 = Utf8 (Ljava/lang/String;)Z
#30 = NameAndType #28:#29 // invokeExact:(Ljava/lang/String;)Z
#31 = Methodref #27.#30 // java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;)Z
#32 = NameAndType #7:#6 // trueTarget:Ljava/lang/invoke/MethodHandle;
#33 = Fieldref #2.#32 // TGWD.trueTarget:Ljava/lang/invoke/MethodHandle;
#34 = NameAndType #28:#21 // invokeExact:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
#35 = Methodref #27.#34 // java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
#36 = NameAndType #8:#6 // falseTarget:Ljava/lang/invoke/MethodHandle;
#37 = Fieldref #2.#36 // TGWD.falseTarget:Ljava/lang/invoke/MethodHandle;
#38 = Utf8 Code
#39 = Utf8 StackMapTable
#40 = Utf8 Exceptions
{
final java.lang.invoke.MethodHandle guard;
flags: ACC_FINAL


final java.lang.invoke.MethodHandle trueTarget;
flags: ACC_FINAL


final java.lang.invoke.MethodHandle falseTarget;
flags: ACC_FINAL


public TGWD(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
flags: ACC_PUBLIC, ACC_VARARGS

Code:
stack=0, locals=4, args_size=4
0: aload_0
1: aload_1
2: bipush 0
4: aaload
5: putfield #13 // Field guard:java.lang.invoke.MethodHandle
8: aload_0
9: aload_1
10: bipush 1
12: aaload
13: putfield #15 // Field trueTarget:java.lang.invoke.MethodHandle
16: aload_0
17: aload_1
18: bipush 2
20: aaload
21: putfield #17 // Field falseTarget:java.lang.invoke.MethodHandle
24: return

public void eval();
flags: ACC_PUBLIC

Code:
stack=0, locals=1, args_size=1
0: return

public java.lang.String Hello(java.lang.String, java.lang.String) throws java.lang.Throwable;
flags: ACC_PUBLIC

Code:
stack=0, locals=3, args_size=3
0: aload_0
1: getfield #25 // Field guard:Ljava/lang/invoke/MethodHandle;
4: aload_1
5: invokevirtual #31 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;)Z
8: ifeq 21
11: aload_0
12: getfield #33 // Field trueTarget:Ljava/lang/invoke/MethodHandle;
15: aload_1
16: aload_2
17: invokevirtual #35 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
20: areturn
21: aload_0
22: getfield #37 // Field falseTarget:Ljava/lang/invoke/MethodHandle;
25: aload_1
26: aload_2
27: invokevirtual #35 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
30: areturn
StackMapTable: number_of_entries = 1
frame_type = 21 /* same */

Exceptions:
throws java.lang.Throwable
}

有人知道生成的字节码哪里出了问题吗?谢谢。我还在此处附加了类文件 Class File ..

以下信息可能有用:1、根据堆栈,我猜问题出在三名现场成员身上。我使用下面的代码来生成这些字段:

FieldVisitor fv;
fv = cw.visitField(ACC_FINAL, 'guard', "Ljava/lang/..", null, null);
fv.visitEnd();

我将 ACC_FINAL 更改为 ACC_PRIVATE。结果是相同的,只是 javap -v 结果中没有显示三个字段成员。

2、基类BaseTemplate是一个空的抽象类,定义为:

public abstract class BaseTemplate { }

================================更新:

更改原始代码中的 putfield 指令后

mv.visitFieldInsn(PUTFIELD, className, list.get(i).name(), list.get(i).type());

mv.visitFieldInsn(PUTFIELD, className, list.get(i).name(),Utils.getFieldDesc(list.get(i).type()));,此时类加载成功。原因是错误的字段签名集(如 @Holger 答案中所示)。

最佳答案

您使用“java.lang.invoke.MethodHandle”作为字段签名而不是正确的“Ljava/lang/invoke/MethodHandle;”生成了构造函数。这可以在 javap 输出中通过以下行看到:

     5: putfield      #13             // Field guard:java.lang.invoke.MethodHandle

13: putfield #15 // Field trueTarget:java.lang.invoke.MethodHandle

21: putfield #17 // Field falseTarget:java.lang.invoke.MethodHandle

Hello 方法正确使用:

     1: getfield      #25             // Field guard:Ljava/lang/invoke/MethodHandle;

12: getfield #33 // Field trueTarget:Ljava/lang/invoke/MethodHandle;

22: getfield #37 // Field falseTarget:Ljava/lang/invoke/MethodHandle;

这也解释了常量池相当大的原因。项目#11 包含错误的java.lang.invoke.MethodHandle 签名,该签名随后由构造函数使用的后续项目#12 - #17 使用。这些与 Hello 方法中使用的项目 #25、#33 和 #37 不同。在正确生成的类中,这些指令共享常量池中的相同项目(它们都间接引用正确的签名Ljava/lang/invoke/MethodHandle;,该签名存储在该类文件的第6项中。

关于java - 无法加载动态生成的字节码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28977883/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com