2013-06-23 20 views
3

我想了解类是如何工作的。我想使用此代码最终字段值在字节码生成中不起作用

dout.writeShort(1);//field count 
    dout.writeShort(Modifier.PUBLIC|Modifier.STATIC|Modifier.FINAL);//modifiers 
    dout.writeShort(utfConstant("jjj"));//name 
    dout.writeShort(utfConstant("I"));//signature 
    dout.writeShort(1);//attribute count 
    dout.writeShort(utfConstant("ConstantValue"));//constant value attribute 
    dout.writeShort(2);//size of attribute 
    dout.writeShort(intConstant(8));//value 

最后的字段添加到我的课,但当我尝试编译它

Exception in thread "main" java.lang.ClassFormatError: Invalid ConstantValue field attribute length 131082 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:161) 
    at Bytecode.BytecodeTest.makeClass(BytecodeTest.java:39) 
    at Bytecode.BytecodeTest.buildClass(BytecodeTest.java:24) 
    at Bytecode.BytecodeTest.main(BytecodeTest.java:17) 

这里我得到这个错误是我的其他代码

private void writeConstantPool(DataOutputStream dout) throws IOException 
    { 
     dout.writeShort(poolIndex); 

     for (Data data : poolMap) 
     { 
      int tag = (byte) data.getData()[0]; 
      dout.writeByte(tag); 

      switch (tag) 
      { 
      case CONSTANT_Utf8: 
       dout.writeUTF((String) data.getData()[1]); 
       break; 
      case CONSTANT_Class: 
       dout.writeShort((Integer) data.getData()[1]); 
       break; 
      case CONSTANT_Integer: 
       dout.writeInt((Integer) data.getData()[1]); 
       break; 
      default: 
       throw new RuntimeException(); 
      } 
     } 
    } 

    private int utfConstant(String s) 
    { 
     return constant(CONSTANT_Utf8, s); 
    } 

    private int intConstant(int i) 
    { 
     return constant(CONSTANT_Integer, i); 
    } 

    private int classConstant(String s) 
    { 
     int classNameIndex = utfConstant(s.replace('.', '/')); 
     return constant(CONSTANT_Class, classNameIndex); 
    } 

    private int constant(Object... data) 
    { 
     Data constantData = new Data(data); 

     if (poolMap.contains(constantData)) 
      return poolMap.indexOf(constantData)+1; 

     poolMap.add(poolIndex-1, constantData); 
     return poolIndex++; 
    } 

    private final Stack<Data> poolMap = new Stack<Data>(); 
    private int poolIndex = 1; 

    private static class Data 
    { 
     private Object[] data; 

     public Data(Object... data) 
     { 
      this.data = data; 
     } 

     public Object[] getData() 
     { 
      return data; 
     } 

     public boolean equals(Object o) 
     {   
      if(o instanceof Data) 
      { 
       Data other = (Data) o; 
       return Arrays.equals(data, other.getData()); 
      } 

      return false; 
     } 
    } 

我这样做的方式是通过生成所有的方法和字段,然后生成常量池,然后我将常量池放在方法和字段之前的字节数组中。

任何人都可以告诉我我在做什么错我可以显示更多的代码,如果有必要,另外我认为这个问题可能与intConstant或常量值属性。

用字节码编辑器看这个后,它看起来像intConstant方法工作正常,所以我认为它是没有工作的字段代码。另外我看了一个字节码编辑器中的一个常量,它看起来是一样的我很困惑。

+0

我曾经不得不使用bytcode操作,而我所做的就是编写一个简单的java类,其中包含相当于我想要在字节码中完成的源代码。我编译了这个类,然后用javap来查看字节码是什么。此外,JVM规范可能会非常有用。 – user3001

+0

我知道我已经尝试了两个,我已经看了字节码中的常量值属性,我仍然不能看到我做错了什么。 – Popgalop

+0

你可以发布类文件本身吗?我可以看看有什么不对。 – Antimony

回答

2

我认为属性的length应该是一个32位整数,而不是一个16位短。

+0

好的。即使有经验,也很难发现这些事情。 – Antimony

+0

是的,这是问题 – Popgalop