jakarta-bcel-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Konstantin Scheglov <scheglov...@nlmk.ru>
Subject Re[2]: Invalid constant pool reference: 28088. Constant pool size is: 1024
Date Thu, 12 Jun 2003 08:25:25 GMT
Hello Stephen,

Thursday, June 12, 2003, 11:56:21 AM, you wrote:

SK> Kosja, we are strange guys.
SK> Who checked the bug reports?
SK> Nobody...
SK> But should:
SK> http://nagoya.apache.org/bugzilla/show_bug.cgi?id=18323
  Ok, thanks. But to find this bug I should already to know, what to
search. :-)

SK> (I investigated the code. Actually nobody invokes setSize(), when 
SK> reading from file; and NOONE sets proper length of LDC_W, when reading 
SK> from file (i think), and it stays 0 all the time. The fix you made in 
SK> dump() forces dumping with proper length  for the proper instruction).
  LDC_W.initFromFile calls LDC.setIndex, which call LDC.setSize()
  Well, may be my fix is not enough, it just dumps right bytes, but
length is still wrong.
  As I can see, there was version 1.2 of LDC_W with:
    opcode = org.apache.bcel.Constants.LDC_W;
    length = 3;
  but in 1.3 there was "bug fix" and length change was removed.

SK> Strange, I have passed near a MB bytecode through BCEL, and had never 
SK> seen this bug in action.
  Yes, I and users of my tool also process many MB of code, but
as you can see, sometimes this happens. I have sample class (about 500
bytes length). Most probably this class also was automatically
generated, and generator is not smart enough to use LDC when index is
small, so it uses LDC_W and this causes problem. I think javac/jikes
use LDC where this is possible, so you just never see such cases.

SK> About method copy:
SK> class Class1 {
SK> void method1() {
SK> // getstatic <System.out>
SK> // ldc #3 <String "Hello world">!!!!!
SK> // invokevirtual <PrintStream::println(String)>
SK> // return
SK> }
SK> }

SK> if you want to copy method1 to _another_ class, you have to make sure 
SK> that ldc "Hello world" points somewhere in the new constantpool where 
SK> you have "Hello world". Complications are pouring in when you want the 
SK> copied method to reference methods of its containing class; or to 
SK> checkcast if a reference points to instance of the enclosing class.
  Thank you.
  I just replace methods in each class with a little changed methods,
so I think, that changing of constant pool is not required.

SK> Konstantin Scheglov wrote:

>>Hello Stephen,
>>Wednesday, June 11, 2003, 7:11:16 PM, you wrote:
>>  Ok, now I am sure, that this is bug in BCEL.
>>  Here is code from LDC_W:
>>  protected void initFromFile(ByteSequence bytes, boolean wide)
>>       throws IOException
>>  {
>>    setIndex(bytes.readUnsignedShort());
>>    // Override just in case it has been changed
>>    opcode = org.apache.bcel.Constants.LDC_W;
>>  }
>>  As you can see, it forces instruction code to LDC_W.
>>  And here is code from LDC:
>>  public final void setIndex(int index) {
>>    super.setIndex(index);
>>    setSize();
>>  }
>>  protected final void setSize() {
>>    if(index <= org.apache.bcel.Constants.MAX_BYTE) { // Fits in one byte?
>>      opcode = org.apache.bcel.Constants.LDC;
>>      length = 2;
>>    } else {
>>      opcode = org.apache.bcel.Constants.LDC_W;
>>      length = 3;
>>    }
>>  }
>>  I.e. setSize() changes inscruction code and length. Then, length
>>used in dump() to detect, that byte or short argument is needed:
>>  public void dump(DataOutputStream out) throws IOException {
>>    out.writeByte(opcode);
>>    if(length == 2)
>>      out.writeByte(index);
>>    else // Applies for LDC_W
>>      out.writeShort(index);
>>  }
>>  But we have (in my case) length == 2, i.e. one byte and LDC_W
>>instruction! So, when it tryies to create String for this instruction,
>>it reads one random byte (in reallity next instruction)!
>>  When I change dump() to this code, I receive no exceptions.
>>  public void dump(DataOutputStream out) throws IOException {
>>    out.writeByte(opcode);
>>    if(opcode == org.apache.bcel.Constants.LDC)
>>      out.writeByte(index);
>>    else // Applies for LDC_W
>>      out.writeShort(index);
>>  }
>>SK> The code you sent is OK, at least for BCEL 5.0 and 5.1 (I have 
>>SK> experience with those). The problem is elsewere.
>>SK> Btw, did you checked if your original (not instrumented) classes are 
>>SK> acceptible? It is so stupid mistake, that you have to be genious to 
>>SK> avoid it, at least I can not :))).
>>SK> Beside this: if you copy method from one class to another (i do not what 
>>SK> are your real application), you must change the constant pool indices of 
>>SK> the instructions.
>>SK> Konstantin Scheglov wrote:
>>>> I use following code to instrument one class.
>>>> But when I instrument some classes and try to print debug
>>>>information, I receive following exception.
>>>>org.apache.bcel.classfile.ClassFormatException: Invalid constant pool reference:
28088. Constant pool size is: 1024
>>>>       at org.apache.bcel.classfile.ConstantPool.getConstant(ConstantPool.java:242)
>>>>       at org.apache.bcel.classfile.Utility.codeToString(Utility.java:369)
>>>>       at org.apache.bcel.classfile.Utility.codeToString(Utility.java:166)
>>>>       at org.apache.bcel.classfile.Code.toString(Code.java:326)
>>>>       at org.apache.bcel.classfile.Code.toString(Code.java:352)
>>>>       at java.lang.String.valueOf(String.java:2131)
>>>>       at java.io.PrintStream.print(PrintStream.java:462)
>>>>       at java.io.PrintStream.println(PrintStream.java:599)
>>>>       at ru.nlmk.eclipse.plugins.profiler.trace.Trace.instrumentClass(Trace.java:1190)
>>>>       at ru.nlmk.eclipse.plugins.profiler.trace.test.TestBCEL.main(TestBCEL.java:23)
>>>>As you can see, I just copy code from one method to another (in real application
>>>>I change code a little). And when I try to load this class in real application
>>>>I receive exception like this from JVM:  "VerifyError: Illegal constant pool
>>>>       public static JavaClass instrumentClass(JavaClass clazz) throws Exception
>>>>               ClassGen classGen = new ClassGen(clazz);
>>>>               ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool());
>>>>               classGen.setConstantPool(cp);
>>>>               //
>>>>               for (int i = 0; i < clazz.getMethods().length; i++) {
>>>>                       Method method = clazz.getMethods()[i];
>>>>                       if (method.isAbstract() || method.isNative())
>>>>                               continue;
>>>>                       if (method.getName().equals("finalize"))
>>>>                               continue;
>>>>                       MethodGen mg = new MethodGen(method, clazz.getClassName(),
>>>>                       mg.setConstantPool(cp);
>>>>                       Method newMethod = mg.getMethod();
>>>>                       if (m_Debug) {
>>>>                               System.out.println(method.getCode());
>>>>                               System.out.println(newMethod.getCode());
>>>>                       }
>>>>                       classGen.replaceMethod(method, newMethod);
>>>>               }
>>>>               //
>>>>               JavaClass newClazz = classGen.getJavaClass();
>>>>               newClazz.setConstantPool(cp.getFinalConstantPool());
>>>>               return newClazz;
>>>>       }
>>>> What I do wrong?
>>>> I see such exception only on few classes (methods).
>>>> I have example of such class.
>>SK> ---------------------------------------------------------------------
>>SK> To unsubscribe, e-mail: bcel-user-unsubscribe@jakarta.apache.org
>>SK> For additional commands, e-mail: bcel-user-help@jakarta.apache.org

Best regards,
 Konstantin                            mailto:scheglov_ke@nlmk.ru

To unsubscribe, e-mail: bcel-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: bcel-user-help@jakarta.apache.org

View raw message