2013-06-23 5 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

한 번 바이트 코드 조작을해야했는데, 내가 한 일은 바이트 코드에서 원했던 것과 동등한 소스 코드가 들어있는 간단한 자바 클래스를 작성하는 것이 었습니다. 그 클래스를 컴파일 한 다음 javap을 사용하여 바이트 코드를 확인했습니다. 또한 JVM 사양도 매우 유용 할 수 있습니다. – user3001

+0

나는 둘 다 시도하고 바이트 코드에서 상수 값 특성을 살펴 봤는데 아직도 내가 뭘 잘못하고 있는지 볼 수 없습니다. – Popgalop

+0

클래스 파일 자체를 게시 할 수 있습니까? 무엇이 잘못되었는지 살펴볼 수 있습니다. – Antimony

답변

2

속성의 length은 16 비트 단락이 아닌 32 비트 정수로 간주됩니다.

+0

잘자요. 경험이 있더라도 이러한 것들을 발견하는 것은 어렵습니다. – Antimony

+0

예, 문제가되었습니다. – Popgalop