Kosja, we are strange guys.
Who checked the bug reports?
Nobody...
But should:
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=18323

(I investigated the code. Actually nobody invokes setSize(), when reading from file; and NOONE sets proper length of LDC_W, when reading from file (i think), and it stays 0 all the time. The fix you made in dump() forces dumping with proper length for the proper instruction).

Strange, I have passed near a MB bytecode through BCEL, and had never seen this bug in action.

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

if you want to copy method1 to _another_ class, you have to make sure that ldc "Hello world" points somewhere in the new constantpool where you have "Hello world". Complications are pouring in when you want the copied method to reference methods of its containing class; or to checkcast if a reference points to instance of the enclosing class.

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 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]








Reply via email to