Mark Crocker | 5 Jun 2003 21:44

Re: the StackMap attribute


On Mon, 26 May 2003 05:33:05 +0400, Igor Maznitsa wrote:

I'm so sorry that this reply has taken so long, but I've been busy :)

>  How to use the StackMap attribute in BCEL? Could anyone show a simple
>  source example? I have interest to change an exist Java class what
>  contains methods with the attribute and I'd like to know how to update
>  the attribute when I have changed the code of a method...

BCEL doesn't have any facilities for creating a new StackMap.  The StackMap is there because they exist in
J2ME MIDP class files and BCEL needs a structure to read the data into and write it back out from.

Creating a StackMap from scratch is difficult.  Calculating the StackMapEntry's requires a complex,
iterative data flow analysis.  To complicate things, Sun's preverifier has a number of bugs, so any
StackMap generator would have to emulate Sun's bugs in order to work reliably.

Even when you know what StackMapEntry's you want to include in a StackMap object, it is not entirely trivial
to create the instance because you need to do all sorts of calculations to figure out the parameters in the
constructor.  In addition, you need to make sure that the ConstantPool has an entry for "StackMap".  If this
is all you want, I can post some code examples of how to do this.

The open source version of the Purifier1 project (see
http://www.markcrocker.com/~mcrocker/Computer/Purifier/) does was an attempt to create a
substitute for Sun's preverifier, and, consequently, it does calculate and create StackMaps.  However,
the first attempt failed to duplicate all of Sun's idiosyncrasies because the Purifier1 project
attempted to speed up the horrifically intensive calculations required of the data flow analysis by
using a different analysis technique.  Although the technique is MUCH faster, it did not always (~95%)
produce the same results as Sun's preverifier.  At that point, funding ran out and the project was moved to a
commercial venture with an algorithm that follows Sun's algorithm more closely.  The commercial version
(Continue reading)

jpicard | 6 Jun 2003 15:49
Picon
Favicon

New instance of a modified class


How to obtain a new instance of a class which was modified by BCEL?

When I execute this code, a exception "java.lang.NoSuchFieldError" appears.

The goal of  this code is to remove the field "libelle".

Have you an idea ?

thanks.

    ClassGen clazz =new ClassGen(Repository.lookupClass(GenerateurVapeur.class));

    // Get the field "libelle".
    Field prpReelle =  clazz.containsField("libelle");

    // Remove the field.	
    if(prpReelle!=null)
         clazz.removeField(prpReelle);
		
    JavaClass classeJava = clazz.getJavaClass();

    try{

      // Save the class
      dumpClass(classeJava,GenerateurVapeur.class);

      org.apache.bcel.util.ClassLoader cl = new
org.apache.bcel.util.ClassLoader(ClassLoader.getSystemClassLoader());

(Continue reading)

Stephen Kolaroff | 6 Jun 2003 16:29
Favicon

Re: New instance of a modified class

Hi
Unfortunately, you have to override some methods of BCEL's class loader 
to get actually class instrumentation/generation on the fly. Even so, 
because of the JLS (or JVM spec, I am not sure right now), you can not 
have different byte code for classes with same name loaded with the same 
class loader. I am affraid, beacuse of this you can never execute:

      GenerateurVapeur newInstance = (GenerateurVapeur)newClass.newInstance();

in your code without ClassCastException (newClass' instances will be 
thought as different, unassignable to GenerateurVapeur; GenerateurVapeur 
already loaded by your context classloader several lines above). I must 
confess, I have never tried this, so if you have success, pls, inform me.

What I am doing when have to do what you want:
1. Obtain JavaClass from a repository without using any Class-es, just 
String names.
2. Mess with the class, and make it implement a useful interface.
3. Dump the class into a fake classloader or even on the disk.
4. Load the class and typecast to the useful interface
5. enjoy

jpicard <at> free.fr wrote:

>How to obtain a new instance of a class which was modified by BCEL?
>
>When I execute this code, a exception "java.lang.NoSuchFieldError" appears.
>
>The goal of  this code is to remove the field "libelle".
>
(Continue reading)

Konstantin Scheglov | 11 Jun 2003 16:17
Picon

Invalid constant pool reference: 28088. Constant pool size is: 1024


  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 reading)

Simon Bretin | 11 Jun 2003 16:52
Favicon

Re: Invalid constant pool reference: 28088. Constant pool size is: 1024

Hi,

I'm no BCEL guru, but I used it for a while a few weeks back, so maybe I 
can help you.

I think the problem must come from the few operations you says you do, 
but that don't show up on the listing you sent ... Maybe you could send 
the whole thing.

Maybe one thing, I think you need to call classGen.update() once you 
changed the method ... But I don't think this will be the cause of your 
problem.

Simon.

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)
(Continue reading)

Konstantin Scheglov | 11 Jun 2003 17:00
Picon

Re[2]: Invalid constant pool reference: 28088. Constant pool size is: 1024

Hello Simon,

Wednesday, June 11, 2003, 6:52:25 PM, you wrote:

SB> I'm no BCEL guru, but I used it for a while a few weeks back, so maybe I
SB> can help you.
  Would be great. :-)

SB> I think the problem must come from the few operations you says you do, 
SB> but that don't show up on the listing you sent ... Maybe you could send 
SB> the whole thing.
  No, problem appears even when I don't modify method. I.e. when I use
code in initial mail.

SB> Maybe one thing, I think you need to call classGen.update() once you 
SB> changed the method ... But I don't think this will be the cause of your 
SB> problem.
  Yes, just tryed - still same exception.

  Here is archive with class. Name of class is broken, but I don't
think, that this is reason of exception.

section 1 of uuencode 5.25 of file clazz.zip    by R.E.M.

sum -r/size 64782/3098 section (from "begin" to "end")
sum -r/size 25249/2228 entire input file

SB> Simon.

SB> Konstantin Scheglov wrote:
(Continue reading)

Stephen Kolaroff | 11 Jun 2003 17:11
Favicon

Re: Invalid constant pool reference: 28088. Constant pool size is: 1024

The code you sent is OK, at least for BCEL 5.0 and 5.1 (I have 
experience with those). The problem is elsewere.
Btw, did you checked if your original (not instrumented) classes are 
acceptible? It is so stupid mistake, that you have to be genious to 
avoid it, at least I can not :))).
Beside this: if you copy method from one class to another (i do not what 
are your real application), you must change the constant pool indices of 
the instructions.

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
(Continue reading)

Stephen Kolaroff | 11 Jun 2003 17:13
Favicon

Re: Invalid constant pool reference: 28088. Constant pool size is: 1024

Sorry, I forgot a think: try verifying with BCEL's verifier: extremly 
useful utility. It have stand alone gui, but you can access its command 
line interface: org.apache.bcel.verifier.Main.main("ru.tum.tum.ClassName");
Konstantin Scheglov | 12 Jun 2003 05:48
Picon

Re[2]: Invalid constant pool reference: 28088. Constant pool size is: 1024

Hello Stephen,

Wednesday, June 11, 2003, 7:11:16 PM, you wrote:

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.
  I also used 5.0 and when saw exception switched to 5.1, but
exception is still here. :-(

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 :))).
  I tryied to post UUE with original class, but it seems, that UUE are
not accepted by mail list.
  I am not sure, but I think, that original class itself is generated
directly in bytecode. It is EJB skeleton, generated by WebLogic. I
write profiler for Eclipse, it can handle almost all classes except
such already generated classes from WebLogic and CGLIB. For CGLIB I
don't have example, but for WebLogic I do.
  I do try to check with _original_ class. And this exception ("Invalid
constant pool reference: 28088. Constant pool size is: 1024") appears
with it! I.e. I just load this class and create copy of each method
using MethodGen. I don't change code. Just copy, as you can see in
code. And even in this case I receive such exception. :-(

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.
  In my test code I just copy code. Do I still need to make these
changes? Can you give me example?
(Continue reading)

Konstantin Scheglov | 12 Jun 2003 05:51
Picon

Re[2]: Invalid constant pool reference: 28088. Constant pool size is: 1024

Hello Stephen,

Wednesday, June 11, 2003, 7:13:39 PM, you wrote:

SK> Sorry, I forgot a think: try verifying with BCEL's verifier: extremly 
SK> useful utility. It have stand alone gui, but you can access its command 
SK> line interface: org.apache.bcel.verifier.Main.main("ru.tum.tum.ClassName");
  There is no such class in bcel.jar.
  There is org.apache.bcel.verifier.GraphicalVerifier, but when I try
to start it, it shows several classes, two green panels and hangs with
infinite "PLEASE WAIT" message on window caption. Is this normal?

SK> ---------------------------------------------------------------------
SK> To unsubscribe, e-mail: bcel-user-unsubscribe <at> jakarta.apache.org
SK> For additional commands, e-mail: bcel-user-help <at> jakarta.apache.org

--

-- 
Best regards,
 Konstantin                            mailto:scheglov_ke <at> nlmk.ru

Gmane