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 index".
>>
>>
>>        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(), 
>> cp);
>>                        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: [EMAIL PROTECTED]
SK> For additional commands, e-mail: [EMAIL PROTECTED]



-- 
Best regards,
 Konstantin                            mailto:[EMAIL PROTECTED]


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to