我正在尝试生成一个名为hello的方法,该方法使用动态字节码生成返回值2。这是我目前的代码。生成方法。
dout.writeShort(Modifier.PUBLIC);//class modifier
dout.writeShort(classConstant("test"));//class name
dout.writeShort(classConstant(Object.class.getName()));//superclass
dout.writeShort(0);//interface count
dout.writeShort(0);//field count
dout.writeShort(1);//method count
dout.writeShort(Modifier.PUBLIC|Modifier.STATIC);//modifiers
dout.writeShort(utfConstant("test"));//name
dout.writeShort(utfConstant(methodDescriptor(int.class, new Class[]{})));//descriptor
dout.writeShort(1);//attribute count
dout.writeShort(utfConstant("Code"));//attribute name
dout.writeInt(34);//attribute length
dout.writeShort(1);//max stack
dout.writeShort(0);//max locals
dout.writeInt(2);//code length
dout.writeByte(0x05);//iconst_2 opcode
dout.writeByte(0xAC);//ireturn opcode
dout.writeShort(0);//exception count
dout.writeShort(0);//attribute count
dout.writeShort(0);//class attributes
问题是,当我运行此代码时,我得到此异常
Exception in thread "main" java.lang.ClassFormatError: Invalid method Code length 0 in class file test
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
at Bytecode.BytecodeTest$BytecodeClassLoader.buildClass(BytecodeTest.java:229)
at Bytecode.BytecodeTest.makeClass(BytecodeTest.java:42)
at Bytecode.BytecodeTest.buildClass(BytecodeTest.java:27)
at Bytecode.BytecodeTest.main(BytecodeTest.java:19)
奇怪的是我正在使代码长度大于0我正在制作它2.我回过头了oracle规范,但它仍然看起来正确。我有一种感觉,我把一些数据写成错误的类型,但我仍然无法找到问题。
答案 0 :(得分:1)
Hotspot验证程序的未记录功能是,对于版本< = 45.2,它对代码属性中的某些字段使用较短的字段长度。这就是为什么将版本更改为49修复所有内容。
如果您使用Krakatau,它会自动处理此问题,但我还没有看到任何其他工具来处理这种情况。
幸运的是,第一个稳定的Java公共版本是45.3,所以你不太可能在野外看到这样的合法代码。但这对于阻止逆向工程师来说是一个巧妙的伎俩。
答案 1 :(得分:0)
嗯,有一件事让我印象深刻的是属性长度:根据我的统计,它应该是14(不是34)。您似乎也缺少类属性计数。
它可能会帮助您定义一些用于编写属性的辅助方法,以确保您正确地计算和编写长度,例如:
private int writeAttribute(final String attributeName) {
dout.putShort(utfConstant(attributeName));
dout.putInt(0);
return dout.position();
}
private void endAttribute(final int attributeStart) {
dout.putInt(attributeStart- 4, dout.position() - attributeStart);
}
private void writeCode() {
final int codeAttributeStart = writeAttribute("Code");
dout.writeShort(1);//max stack
dout.writeShort(0);//max locals
dout.writeInt(2);//code length
dout.writeByte(0x05);//iconst_2 opcode
dout.writeByte(0xAC);//ireturn opcode
dout.writeShort(0);//exception count
dout.writeShort(0);//attribute count
endAttribute(codeAttributeStart);
}
另外,请确保您写出的 classfile minor / major version 符合您所遵循的规范 - 格式会不时更改:)。