jakarta-bcel-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stephen Kolaroff <che...@riflexo.com>
Subject Re: Invalid constant pool reference: 28088. Constant pool size is: 1024
Date Thu, 12 Jun 2003 09:06:25 GMT
Hello Konstantin

I found the problem (again:)), and posting this so anybody interested 
can read from one place.
Last time I did not noticed the setSize() invokation from within 
initFromFile.
What happens:
setSize() makes the proper length and changes the opcode (hmm, I am not 
sure I want BCEL to change compiled code without my confirmation, but 
who cares!). The next line in the initFromFile _restores_ the old opcode 
(LDC_W), thus making opcode and length inconsistent. The problem shows 
only when compiled code contains LDC_W with index less than MAX_BYTE 
(when LDC suffice), and, therefore, shows up very rarely.

Konstantin Scheglov wrote:

>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 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: bcel-user-unsubscribe@jakarta.apache.org
>>>SK> For additional commands, e-mail: bcel-user-help@jakarta.apache.org
>>>
>>>
>>>
>>> 
>>>
>>>      
>>>
>
>
>
>
>  
>


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message