You are viewing a plain text version of this content. The canonical link for it is here.
Posted to bcel-user@jakarta.apache.org by Dmitri Colebatch <di...@colebatch.com> on 2002/10/13 17:05:19 UTC

two questions: classloading, and NoSuchMethodFoundErrors on on-the-fly generated classes

Hey all,

I'm hoping this isn't too much of a newbie post - I have done a search
through the archives, and read the manual... if there's something else I
should have looked at before writing this, then please point me there (o:

First things first.  My requirements are to dynamically implement an
abstract class.  The test case I have (see end of email for my hacky src
code) is one where I create a class, and then load it using my classloader
(subclasses bcel.util.ClassLoader), and then two tests - try to call a
method through reflection, and try to cast it to the superclass.

reflection does all sorts of weird things:

add method = public void
com.colebatch.$$BCEL$$GeneratedObject.add(java.lang.Object)
java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodError
 at com.colebatch.$$BCEL$$GeneratedObject.add(<generated>)

which comes from this bit of code:

    java.lang.reflect.Method method = o.getClass().getMethod("add", new
Class[] { Object.class } );
    System.out.println("add method = " + method);
    method.invoke(o, new Object[] {"foo"});

which I find _really_ weird, I would have expected getMethod(..) line to
fail, but we get passed that, and then apparently the method doesn't exist.

casting behaves a little more understandably.... in that, it does't cast.
Simple though, because the superclass is loaded by two different class
loaders:

TestSuperClass.class = sun.misc.Launcher$AppClassLoader@71732b
clazz.getSuperclass() = com.colebatch.TestBCEL$1@70eed6

(from code:)

      System.out.println("TestSuperClass.class = " +
TestSuperClass.class.getClassLoader());
      System.out.println("clazz.getSuperclass() = " +
clazz.getSuperclass().getClassLoader());

I assume what happes here is that the bcel classloader loads the child
class, and all its superclasses....  looking through the code, modifyClass
(whilst not doing anything) ensures that the class is loaded by the bcel cl.
Am I being naive/stupid thinking that I can use on-the-fly generated classes
without using JavaWrapper?  At this stage there's no real reason why I
couldn't use it, but I'd prefer to be as hands-off as I can be at this
point.

any feedback on either of the above issues would be greatly appreciated.

cheers
dim

------------------- src code here -----------------

package com.colebatch;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.bcel.Constants;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ALOAD;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.FieldGen;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.RETURN;
import org.apache.bcel.generic.Type;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestBCEL extends TestCase implements Constants
{
  public TestBCEL(String name)
  {
    super(name);
  }

  public static Test suite()
  {
    return new TestSuite(TestBCEL.class);
  }

  public static void main(String[] args) throws Exception
  {
    new TestBCEL("foo").testBCEL();
  }


//-------------------------------------------------------------------------
  // tests

  public void testBCEL()
    throws Exception
  {
    final String superClassName = "com.colebatch.TestSuperClass";
    final String className = "com.colebatch.$$BCEL$$GeneratedObject";

    ClassGen cg = new ClassGen(className, superClassName,
                               "<generated>", ACC_PUBLIC | ACC_SUPER,
                               null);
    ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool

    String ctxFieldName = "list";
    ObjectType ctxType = new ObjectType("java.util.List");

    addField(ctxType, ctxFieldName, cp, cg);
    addConstructor(cg, cp, superClassName, className, ctxFieldName,
ctxType);
    addMethod(cg, cp, className, ctxFieldName, ctxType);

    final Map classes = new HashMap();

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    cg.getJavaClass().dump(baos);
    classes.put(className, baos.toByteArray());

    org.apache.bcel.util.ClassLoader cl = new
org.apache.bcel.util.ClassLoader()
    {
      protected JavaClass createClass(String class_name)
      {
        byte[]      bytes  = (byte[]) classes.get(class_name);
        ClassParser parser = new ClassParser(new
ByteArrayInputStream(bytes), "<generated>");

        JavaClass clazz = null;

        try
        {
          clazz = parser.parse();

          dump(clazz, null, class_name);

          // Adapt the class name to the passed value
          ConstantPool cp = clazz.getConstantPool();

          ConstantClass cl =
(ConstantClass)cp.getConstant(clazz.getClassNameIndex(),
                       Constants.CONSTANT_Class);
          ConstantUtf8 name =
(ConstantUtf8)cp.getConstant(cl.getNameIndex(),
                       Constants.CONSTANT_Utf8);
          name.setBytes(class_name.replace('.', '/'));

          return clazz;
        }
        catch (IOException e)
        {
          throw new RuntimeException(e.getMessage());
        }
      }
    };
    Class clazz = cl.loadClass(className);

    for (int i = 0; i < clazz.getMethods().length; i++)
    {
      java.lang.reflect.Method method = clazz.getMethods()[i];
      System.out.println("method = " + method);
    }

    List list = new ArrayList();
    Constructor constructor = clazz.getConstructor(new Class[]
{List.class});
    Object o = constructor.newInstance(new Object[] {list});
    if (o instanceof TestSuperClass)
    {
      ((TestSuperClass) o).add("foo");
      assertEquals("length not 1", 1, list.size());
      assertEquals("first value not foo", "foo", list.get(0));
      list.remove(0);
    }
    else
    {
      System.out.println("not TestSuperClass");
      System.out.println("clazz.getSuperclass() = " +
clazz.getSuperclass());
      for (int i = 0; i < clazz.getInterfaces().length; i++)
      {
        Class aClass = clazz.getInterfaces()[i];
        System.out.println("implements " + aClass);
      }

      System.out.println("-------------");
      System.out.println("TestSuperClass.class = " +
TestSuperClass.class.getClassLoader());
      System.out.println("clazz.getSuperclass() = " +
clazz.getSuperclass().getClassLoader());
    }

    java.lang.reflect.Method method = o.getClass().getMethod("add", new
Class[] { Object.class } );
    System.out.println("add method = " + method);
    method.invoke(o, new Object[] {"foo"});
    assertEquals("length not 1", 1, list.size());
    assertEquals("first value not foo", "foo", list.get(0));

//    dump(className);
  }

  private void addField(ObjectType ctxType, String ctxFieldName,
ConstantPoolGen cp, ClassGen cg)
  {
    FieldGen fieldGen = new FieldGen(Constants.ACC_PUBLIC, // |
Constants.ACC_FINAL,
                                     ctxType,
                                     ctxFieldName,
                                     cp);
    Field field = fieldGen.getField();
    cg.addField(field);
  }

  public static void dump(String className, String methodName)
  {
    JavaClass clazz = Repository.lookupClass(className);
    dump(clazz, methodName, className);
  }

  private static void dump(JavaClass clazz, String methodName, String
className)
  {
    Method[] methods = clazz.getMethods();
    for (int i = 0; i < methods.length; i++)
    {
      Method method = methods[i];
      if (methodName != null && !method.getName().equals(methodName))
        continue;

      System.out.println("method = " + method);
      ConstantPoolGen cp = new ConstantPoolGen();
      MethodGen methodGen = new MethodGen(method, className, cp);
      InstructionList instructionList = methodGen.getInstructionList();
      Instruction[] instructions = instructionList.getInstructions();
      for (int j = 0; j < instructions.length; j++)
      {
        Instruction instruction = instructions[j];
        System.out.println("instruction = " + instruction);
      }

      System.out.println("");
      System.out.println("-----------------------------------");
      System.out.println("");
    }
  }

  private void addConstructor(ClassGen cg, ConstantPoolGen cp, final String
superClassName, final String className, String ctxFieldName, ObjectType
ctxType)
  {
    InstructionList il = new InstructionList();
    InstructionFactory factory = new InstructionFactory(cg, cp);
    il.append(new ALOAD(0));
    il.append(factory.createInvoke(superClassName, "<init>", Type.VOID, new
Type[0], Constants.INVOKESPECIAL));
    il.append(new ALOAD(0)); // load ctx
    il.append(new ALOAD(1)); // load ctx
    il.append(factory.createPutField(className, ctxFieldName, ctxType));
    il.append(new RETURN());
    MethodGen constructorGen = new MethodGen(Constants.ACC_PUBLIC,
                                             Type.VOID,
                                             new Type[]{ctxType},
                                             new String[]{"list"},
                                             "<init>",
                                             className,
                                             il,
                                             cp);
    constructorGen.setMaxStack();
    cg.addMethod(constructorGen.getMethod());

    il.dispose();
  }


  private void addMethod(ClassGen cg, ConstantPoolGen cp, String className,
String ctxFieldName, ObjectType ctxType)
  {
//    generated:
//    method = public void add(Object o)
//    instruction = aload_0[42](1)
//    instruction = getfield[180](3) 14
//    instruction = aload_1[43](1)
//    instruction = invokeinterface[185](5) 25
//    instruction = pop[87](1)
//    instruction = return[177](1)
//
//    -----------------------------------
//
//    coded:
//    method = public void add(Object o)
//    instruction = aload_0[42](1)
//    instruction = getfield[180](3) 109
//    instruction = aload_1[43](1)
//    instruction = invokeinterface[185](5) 110
//    instruction = pop[87](1)
//    instruction = return[177](1)

    InstructionList il = new InstructionList();
    InstructionFactory factory = new InstructionFactory(cg, cp);
    il.append(new ALOAD(0));
    il.append(factory.createGetField(className, ctxFieldName, ctxType));
    il.append(new ALOAD(1));
    il.append(factory.createInvoke("java.util.List", "add", Type.VOID, new
Type[] {Type.OBJECT}, Constants.INVOKEINTERFACE));
//    il.append(new POP());
    il.append(new RETURN());
    MethodGen mg = new MethodGen(Constants.ACC_PUBLIC,
                                             Type.VOID,
                                             new Type[] {Type.OBJECT},
                                             new String[]{"o"},
                                             "add",
                                             className,
                                             il,
                                             cp);
    mg.setMaxStack();
    cg.addMethod(mg.getMethod());

    il.dispose();
  }

}


package com.colebatch;

public abstract class TestSuperClass
{
  public TestSuperClass()
  {
    System.out.println("TestSuperClass.<init>()");
  }

  public abstract void add(Object o);
}


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: two questions: classloading, and NoSuchMethodFoundErrors on on-the-fly generated classes

Posted by Dmitri Colebatch <di...@bigpond.net.au>.
James,

Thanks for the pointer.... sounds to be what I'm looking for at this
stage...  I'll have a go and let you know if I have any problems..

cheers
dim

----- Original Message -----
From: "Juozas Baliuka" <ba...@centras.lt>
To: "BCEL Users List" <bc...@jakarta.apache.org>
Sent: Monday, October 14, 2002 1:33 AM
Subject: Re: two questions: classloading, and NoSuchMethodFoundErrors on
on-the-fly generated classes


>
> Hi,
>  I am working on the same, possible you will find my project usefull.
>  http://cglib.sourceforge.net it has "Enhancer" for abstract classes.
> You can use it like java.lang.reflect.Proxy. I believe it will help.
>
> > Further to the below, if I override modifyClass to return null I fix the
> > casting problem, but that then goes back to the same
NoClassdefFoundError
> > looking for the method that I think is there (o:
> >
> > again, be greatful for any assistance.
> >
> > cheers
> > dim
> >
> > ----- Original Message -----
> > From: "Dmitri Colebatch" <di...@colebatch.com>
> > To: <bc...@jakarta.apache.org>
> > Sent: Monday, October 14, 2002 1:05 AM
> > Subject: two questions: classloading, and NoSuchMethodFoundErrors on
> > on-the-fly generated classes
> >
> >
> > > Hey all,
> > >
> > > I'm hoping this isn't too much of a newbie post - I have done a search
> > > through the archives, and read the manual... if there's something else
I
> > > should have looked at before writing this, then please point me there
> (o:
> > >
> > > First things first.  My requirements are to dynamically implement an
> > > abstract class.  The test case I have (see end of email for my hacky
src
> > > code) is one where I create a class, and then load it using my
> classloader
> > > (subclasses bcel.util.ClassLoader), and then two tests - try to call a
> > > method through reflection, and try to cast it to the superclass.
> > >
> > > reflection does all sorts of weird things:
> > >
> > > add method = public void
> > > com.colebatch.$$BCEL$$GeneratedObject.add(java.lang.Object)
> > > java.lang.reflect.InvocationTargetException:
java.lang.NoSuchMethodError
> > >  at com.colebatch.$$BCEL$$GeneratedObject.add(<generated>)
> > >
> > > which comes from this bit of code:
> > >
> > >     java.lang.reflect.Method method = o.getClass().getMethod("add",
new
> > > Class[] { Object.class } );
> > >     System.out.println("add method = " + method);
> > >     method.invoke(o, new Object[] {"foo"});
> > >
> > > which I find _really_ weird, I would have expected getMethod(..) line
to
> > > fail, but we get passed that, and then apparently the method doesn't
> > exist.
> > >
> > > casting behaves a little more understandably.... in that, it does't
> cast.
> > > Simple though, because the superclass is loaded by two different class
> > > loaders:
> > >
> > > TestSuperClass.class = sun.misc.Launcher$AppClassLoader@71732b
> > > clazz.getSuperclass() = com.colebatch.TestBCEL$1@70eed6
> > >
> > > (from code:)
> > >
> > >       System.out.println("TestSuperClass.class = " +
> > > TestSuperClass.class.getClassLoader());
> > >       System.out.println("clazz.getSuperclass() = " +
> > > clazz.getSuperclass().getClassLoader());
> > >
> > > I assume what happes here is that the bcel classloader loads the child
> > > class, and all its superclasses....  looking through the code,
> modifyClass
> > > (whilst not doing anything) ensures that the class is loaded by the
bcel
> > cl.
> > > Am I being naive/stupid thinking that I can use on-the-fly generated
> > classes
> > > without using JavaWrapper?  At this stage there's no real reason why I
> > > couldn't use it, but I'd prefer to be as hands-off as I can be at this
> > > point.
> > >
> > > any feedback on either of the above issues would be greatly
appreciated.
> > >
> > > cheers
> > > dim
> > >
> > > ------------------- src code here -----------------
> > >
> > > package com.colebatch;
> > >
> > > import junit.framework.Test;
> > > import junit.framework.TestCase;
> > > import junit.framework.TestSuite;
> > > import org.apache.bcel.Constants;
> > > import org.apache.bcel.Repository;
> > > import org.apache.bcel.classfile.ClassParser;
> > > import org.apache.bcel.classfile.ConstantClass;
> > > import org.apache.bcel.classfile.ConstantPool;
> > > import org.apache.bcel.classfile.ConstantUtf8;
> > > import org.apache.bcel.classfile.Field;
> > > import org.apache.bcel.classfile.JavaClass;
> > > import org.apache.bcel.classfile.Method;
> > > import org.apache.bcel.generic.ALOAD;
> > > import org.apache.bcel.generic.ClassGen;
> > > import org.apache.bcel.generic.ConstantPoolGen;
> > > import org.apache.bcel.generic.FieldGen;
> > > import org.apache.bcel.generic.Instruction;
> > > import org.apache.bcel.generic.InstructionFactory;
> > > import org.apache.bcel.generic.InstructionList;
> > > import org.apache.bcel.generic.MethodGen;
> > > import org.apache.bcel.generic.ObjectType;
> > > import org.apache.bcel.generic.RETURN;
> > > import org.apache.bcel.generic.Type;
> > >
> > > import java.io.ByteArrayInputStream;
> > > import java.io.ByteArrayOutputStream;
> > > import java.io.IOException;
> > > import java.lang.reflect.Constructor;
> > > import java.util.ArrayList;
> > > import java.util.HashMap;
> > > import java.util.List;
> > > import java.util.Map;
> > >
> > > public class TestBCEL extends TestCase implements Constants
> > > {
> > >   public TestBCEL(String name)
> > >   {
> > >     super(name);
> > >   }
> > >
> > >   public static Test suite()
> > >   {
> > >     return new TestSuite(TestBCEL.class);
> > >   }
> > >
> > >   public static void main(String[] args) throws Exception
> > >   {
> > >     new TestBCEL("foo").testBCEL();
> > >   }
> > >
> > >
> > >
> >
>
//-------------------------------------------------------------------------
> > >   // tests
> > >
> > >   public void testBCEL()
> > >     throws Exception
> > >   {
> > >     final String superClassName = "com.colebatch.TestSuperClass";
> > >     final String className = "com.colebatch.$$BCEL$$GeneratedObject";
> > >
> > >     ClassGen cg = new ClassGen(className, superClassName,
> > >                                "<generated>", ACC_PUBLIC | ACC_SUPER,
> > >                                null);
> > >     ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant
> pool
> > >
> > >     String ctxFieldName = "list";
> > >     ObjectType ctxType = new ObjectType("java.util.List");
> > >
> > >     addField(ctxType, ctxFieldName, cp, cg);
> > >     addConstructor(cg, cp, superClassName, className, ctxFieldName,
> > > ctxType);
> > >     addMethod(cg, cp, className, ctxFieldName, ctxType);
> > >
> > >     final Map classes = new HashMap();
> > >
> > >     ByteArrayOutputStream baos = new ByteArrayOutputStream();
> > >     cg.getJavaClass().dump(baos);
> > >     classes.put(className, baos.toByteArray());
> > >
> > >     org.apache.bcel.util.ClassLoader cl = new
> > > org.apache.bcel.util.ClassLoader()
> > >     {
> > >       protected JavaClass createClass(String class_name)
> > >       {
> > >         byte[]      bytes  = (byte[]) classes.get(class_name);
> > >         ClassParser parser = new ClassParser(new
> > > ByteArrayInputStream(bytes), "<generated>");
> > >
> > >         JavaClass clazz = null;
> > >
> > >         try
> > >         {
> > >           clazz = parser.parse();
> > >
> > >           dump(clazz, null, class_name);
> > >
> > >           // Adapt the class name to the passed value
> > >           ConstantPool cp = clazz.getConstantPool();
> > >
> > >           ConstantClass cl =
> > > (ConstantClass)cp.getConstant(clazz.getClassNameIndex(),
> > >                        Constants.CONSTANT_Class);
> > >           ConstantUtf8 name =
> > > (ConstantUtf8)cp.getConstant(cl.getNameIndex(),
> > >                        Constants.CONSTANT_Utf8);
> > >           name.setBytes(class_name.replace('.', '/'));
> > >
> > >           return clazz;
> > >         }
> > >         catch (IOException e)
> > >         {
> > >           throw new RuntimeException(e.getMessage());
> > >         }
> > >       }
> > >     };
> > >     Class clazz = cl.loadClass(className);
> > >
> > >     for (int i = 0; i < clazz.getMethods().length; i++)
> > >     {
> > >       java.lang.reflect.Method method = clazz.getMethods()[i];
> > >       System.out.println("method = " + method);
> > >     }
> > >
> > >     List list = new ArrayList();
> > >     Constructor constructor = clazz.getConstructor(new Class[]
> > > {List.class});
> > >     Object o = constructor.newInstance(new Object[] {list});
> > >     if (o instanceof TestSuperClass)
> > >     {
> > >       ((TestSuperClass) o).add("foo");
> > >       assertEquals("length not 1", 1, list.size());
> > >       assertEquals("first value not foo", "foo", list.get(0));
> > >       list.remove(0);
> > >     }
> > >     else
> > >     {
> > >       System.out.println("not TestSuperClass");
> > >       System.out.println("clazz.getSuperclass() = " +
> > > clazz.getSuperclass());
> > >       for (int i = 0; i < clazz.getInterfaces().length; i++)
> > >       {
> > >         Class aClass = clazz.getInterfaces()[i];
> > >         System.out.println("implements " + aClass);
> > >       }
> > >
> > >       System.out.println("-------------");
> > >       System.out.println("TestSuperClass.class = " +
> > > TestSuperClass.class.getClassLoader());
> > >       System.out.println("clazz.getSuperclass() = " +
> > > clazz.getSuperclass().getClassLoader());
> > >     }
> > >
> > >     java.lang.reflect.Method method = o.getClass().getMethod("add",
new
> > > Class[] { Object.class } );
> > >     System.out.println("add method = " + method);
> > >     method.invoke(o, new Object[] {"foo"});
> > >     assertEquals("length not 1", 1, list.size());
> > >     assertEquals("first value not foo", "foo", list.get(0));
> > >
> > > //    dump(className);
> > >   }
> > >
> > >   private void addField(ObjectType ctxType, String ctxFieldName,
> > > ConstantPoolGen cp, ClassGen cg)
> > >   {
> > >     FieldGen fieldGen = new FieldGen(Constants.ACC_PUBLIC, // |
> > > Constants.ACC_FINAL,
> > >                                      ctxType,
> > >                                      ctxFieldName,
> > >                                      cp);
> > >     Field field = fieldGen.getField();
> > >     cg.addField(field);
> > >   }
> > >
> > >   public static void dump(String className, String methodName)
> > >   {
> > >     JavaClass clazz = Repository.lookupClass(className);
> > >     dump(clazz, methodName, className);
> > >   }
> > >
> > >   private static void dump(JavaClass clazz, String methodName, String
> > > className)
> > >   {
> > >     Method[] methods = clazz.getMethods();
> > >     for (int i = 0; i < methods.length; i++)
> > >     {
> > >       Method method = methods[i];
> > >       if (methodName != null && !method.getName().equals(methodName))
> > >         continue;
> > >
> > >       System.out.println("method = " + method);
> > >       ConstantPoolGen cp = new ConstantPoolGen();
> > >       MethodGen methodGen = new MethodGen(method, className, cp);
> > >       InstructionList instructionList =
methodGen.getInstructionList();
> > >       Instruction[] instructions = instructionList.getInstructions();
> > >       for (int j = 0; j < instructions.length; j++)
> > >       {
> > >         Instruction instruction = instructions[j];
> > >         System.out.println("instruction = " + instruction);
> > >       }
> > >
> > >       System.out.println("");
> > >       System.out.println("-----------------------------------");
> > >       System.out.println("");
> > >     }
> > >   }
> > >
> > >   private void addConstructor(ClassGen cg, ConstantPoolGen cp, final
> > String
> > > superClassName, final String className, String ctxFieldName,
ObjectType
> > > ctxType)
> > >   {
> > >     InstructionList il = new InstructionList();
> > >     InstructionFactory factory = new InstructionFactory(cg, cp);
> > >     il.append(new ALOAD(0));
> > >     il.append(factory.createInvoke(superClassName, "<init>",
Type.VOID,
> > new
> > > Type[0], Constants.INVOKESPECIAL));
> > >     il.append(new ALOAD(0)); // load ctx
> > >     il.append(new ALOAD(1)); // load ctx
> > >     il.append(factory.createPutField(className, ctxFieldName,
ctxType));
> > >     il.append(new RETURN());
> > >     MethodGen constructorGen = new MethodGen(Constants.ACC_PUBLIC,
> > >                                              Type.VOID,
> > >                                              new Type[]{ctxType},
> > >                                              new String[]{"list"},
> > >                                              "<init>",
> > >                                              className,
> > >                                              il,
> > >                                              cp);
> > >     constructorGen.setMaxStack();
> > >     cg.addMethod(constructorGen.getMethod());
> > >
> > >     il.dispose();
> > >   }
> > >
> > >
> > >   private void addMethod(ClassGen cg, ConstantPoolGen cp, String
> > className,
> > > String ctxFieldName, ObjectType ctxType)
> > >   {
> > > //    generated:
> > > //    method = public void add(Object o)
> > > //    instruction = aload_0[42](1)
> > > //    instruction = getfield[180](3) 14
> > > //    instruction = aload_1[43](1)
> > > //    instruction = invokeinterface[185](5) 25
> > > //    instruction = pop[87](1)
> > > //    instruction = return[177](1)
> > > //
> > > //    -----------------------------------
> > > //
> > > //    coded:
> > > //    method = public void add(Object o)
> > > //    instruction = aload_0[42](1)
> > > //    instruction = getfield[180](3) 109
> > > //    instruction = aload_1[43](1)
> > > //    instruction = invokeinterface[185](5) 110
> > > //    instruction = pop[87](1)
> > > //    instruction = return[177](1)
> > >
> > >     InstructionList il = new InstructionList();
> > >     InstructionFactory factory = new InstructionFactory(cg, cp);
> > >     il.append(new ALOAD(0));
> > >     il.append(factory.createGetField(className, ctxFieldName,
ctxType));
> > >     il.append(new ALOAD(1));
> > >     il.append(factory.createInvoke("java.util.List", "add", Type.VOID,
> new
> > > Type[] {Type.OBJECT}, Constants.INVOKEINTERFACE));
> > > //    il.append(new POP());
> > >     il.append(new RETURN());
> > >     MethodGen mg = new MethodGen(Constants.ACC_PUBLIC,
> > >                                              Type.VOID,
> > >                                              new Type[] {Type.OBJECT},
> > >                                              new String[]{"o"},
> > >                                              "add",
> > >                                              className,
> > >                                              il,
> > >                                              cp);
> > >     mg.setMaxStack();
> > >     cg.addMethod(mg.getMethod());
> > >
> > >     il.dispose();
> > >   }
> > >
> > > }
> > >
> > >
> > > package com.colebatch;
> > >
> > > public abstract class TestSuperClass
> > > {
> > >   public TestSuperClass()
> > >   {
> > >     System.out.println("TestSuperClass.<init>()");
> > >   }
> > >
> > >   public abstract void add(Object o);
> > > }
> > >
> > >
> > > --
> > > To unsubscribe, e-mail:
> > <ma...@jakarta.apache.org>
> > > For additional commands, e-mail:
> > <ma...@jakarta.apache.org>
> > >
> > >
> >
> >
> > --
> > To unsubscribe, e-mail:
> <ma...@jakarta.apache.org>
> > For additional commands, e-mail:
> <ma...@jakarta.apache.org>
> >
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: two questions: classloading, and NoSuchMethodFoundErrors on on-the-fly generated classes

Posted by Juozas Baliuka <ba...@centras.lt>.
Hi,
 I am working on the same, possible you will find my project usefull.
 http://cglib.sourceforge.net it has "Enhancer" for abstract classes.
You can use it like java.lang.reflect.Proxy. I believe it will help.

> Further to the below, if I override modifyClass to return null I fix the
> casting problem, but that then goes back to the same NoClassdefFoundError
> looking for the method that I think is there (o:
>
> again, be greatful for any assistance.
>
> cheers
> dim
>
> ----- Original Message -----
> From: "Dmitri Colebatch" <di...@colebatch.com>
> To: <bc...@jakarta.apache.org>
> Sent: Monday, October 14, 2002 1:05 AM
> Subject: two questions: classloading, and NoSuchMethodFoundErrors on
> on-the-fly generated classes
>
>
> > Hey all,
> >
> > I'm hoping this isn't too much of a newbie post - I have done a search
> > through the archives, and read the manual... if there's something else I
> > should have looked at before writing this, then please point me there
(o:
> >
> > First things first.  My requirements are to dynamically implement an
> > abstract class.  The test case I have (see end of email for my hacky src
> > code) is one where I create a class, and then load it using my
classloader
> > (subclasses bcel.util.ClassLoader), and then two tests - try to call a
> > method through reflection, and try to cast it to the superclass.
> >
> > reflection does all sorts of weird things:
> >
> > add method = public void
> > com.colebatch.$$BCEL$$GeneratedObject.add(java.lang.Object)
> > java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodError
> >  at com.colebatch.$$BCEL$$GeneratedObject.add(<generated>)
> >
> > which comes from this bit of code:
> >
> >     java.lang.reflect.Method method = o.getClass().getMethod("add", new
> > Class[] { Object.class } );
> >     System.out.println("add method = " + method);
> >     method.invoke(o, new Object[] {"foo"});
> >
> > which I find _really_ weird, I would have expected getMethod(..) line to
> > fail, but we get passed that, and then apparently the method doesn't
> exist.
> >
> > casting behaves a little more understandably.... in that, it does't
cast.
> > Simple though, because the superclass is loaded by two different class
> > loaders:
> >
> > TestSuperClass.class = sun.misc.Launcher$AppClassLoader@71732b
> > clazz.getSuperclass() = com.colebatch.TestBCEL$1@70eed6
> >
> > (from code:)
> >
> >       System.out.println("TestSuperClass.class = " +
> > TestSuperClass.class.getClassLoader());
> >       System.out.println("clazz.getSuperclass() = " +
> > clazz.getSuperclass().getClassLoader());
> >
> > I assume what happes here is that the bcel classloader loads the child
> > class, and all its superclasses....  looking through the code,
modifyClass
> > (whilst not doing anything) ensures that the class is loaded by the bcel
> cl.
> > Am I being naive/stupid thinking that I can use on-the-fly generated
> classes
> > without using JavaWrapper?  At this stage there's no real reason why I
> > couldn't use it, but I'd prefer to be as hands-off as I can be at this
> > point.
> >
> > any feedback on either of the above issues would be greatly appreciated.
> >
> > cheers
> > dim
> >
> > ------------------- src code here -----------------
> >
> > package com.colebatch;
> >
> > import junit.framework.Test;
> > import junit.framework.TestCase;
> > import junit.framework.TestSuite;
> > import org.apache.bcel.Constants;
> > import org.apache.bcel.Repository;
> > import org.apache.bcel.classfile.ClassParser;
> > import org.apache.bcel.classfile.ConstantClass;
> > import org.apache.bcel.classfile.ConstantPool;
> > import org.apache.bcel.classfile.ConstantUtf8;
> > import org.apache.bcel.classfile.Field;
> > import org.apache.bcel.classfile.JavaClass;
> > import org.apache.bcel.classfile.Method;
> > import org.apache.bcel.generic.ALOAD;
> > import org.apache.bcel.generic.ClassGen;
> > import org.apache.bcel.generic.ConstantPoolGen;
> > import org.apache.bcel.generic.FieldGen;
> > import org.apache.bcel.generic.Instruction;
> > import org.apache.bcel.generic.InstructionFactory;
> > import org.apache.bcel.generic.InstructionList;
> > import org.apache.bcel.generic.MethodGen;
> > import org.apache.bcel.generic.ObjectType;
> > import org.apache.bcel.generic.RETURN;
> > import org.apache.bcel.generic.Type;
> >
> > import java.io.ByteArrayInputStream;
> > import java.io.ByteArrayOutputStream;
> > import java.io.IOException;
> > import java.lang.reflect.Constructor;
> > import java.util.ArrayList;
> > import java.util.HashMap;
> > import java.util.List;
> > import java.util.Map;
> >
> > public class TestBCEL extends TestCase implements Constants
> > {
> >   public TestBCEL(String name)
> >   {
> >     super(name);
> >   }
> >
> >   public static Test suite()
> >   {
> >     return new TestSuite(TestBCEL.class);
> >   }
> >
> >   public static void main(String[] args) throws Exception
> >   {
> >     new TestBCEL("foo").testBCEL();
> >   }
> >
> >
> >
>
//-------------------------------------------------------------------------
> >   // tests
> >
> >   public void testBCEL()
> >     throws Exception
> >   {
> >     final String superClassName = "com.colebatch.TestSuperClass";
> >     final String className = "com.colebatch.$$BCEL$$GeneratedObject";
> >
> >     ClassGen cg = new ClassGen(className, superClassName,
> >                                "<generated>", ACC_PUBLIC | ACC_SUPER,
> >                                null);
> >     ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant
pool
> >
> >     String ctxFieldName = "list";
> >     ObjectType ctxType = new ObjectType("java.util.List");
> >
> >     addField(ctxType, ctxFieldName, cp, cg);
> >     addConstructor(cg, cp, superClassName, className, ctxFieldName,
> > ctxType);
> >     addMethod(cg, cp, className, ctxFieldName, ctxType);
> >
> >     final Map classes = new HashMap();
> >
> >     ByteArrayOutputStream baos = new ByteArrayOutputStream();
> >     cg.getJavaClass().dump(baos);
> >     classes.put(className, baos.toByteArray());
> >
> >     org.apache.bcel.util.ClassLoader cl = new
> > org.apache.bcel.util.ClassLoader()
> >     {
> >       protected JavaClass createClass(String class_name)
> >       {
> >         byte[]      bytes  = (byte[]) classes.get(class_name);
> >         ClassParser parser = new ClassParser(new
> > ByteArrayInputStream(bytes), "<generated>");
> >
> >         JavaClass clazz = null;
> >
> >         try
> >         {
> >           clazz = parser.parse();
> >
> >           dump(clazz, null, class_name);
> >
> >           // Adapt the class name to the passed value
> >           ConstantPool cp = clazz.getConstantPool();
> >
> >           ConstantClass cl =
> > (ConstantClass)cp.getConstant(clazz.getClassNameIndex(),
> >                        Constants.CONSTANT_Class);
> >           ConstantUtf8 name =
> > (ConstantUtf8)cp.getConstant(cl.getNameIndex(),
> >                        Constants.CONSTANT_Utf8);
> >           name.setBytes(class_name.replace('.', '/'));
> >
> >           return clazz;
> >         }
> >         catch (IOException e)
> >         {
> >           throw new RuntimeException(e.getMessage());
> >         }
> >       }
> >     };
> >     Class clazz = cl.loadClass(className);
> >
> >     for (int i = 0; i < clazz.getMethods().length; i++)
> >     {
> >       java.lang.reflect.Method method = clazz.getMethods()[i];
> >       System.out.println("method = " + method);
> >     }
> >
> >     List list = new ArrayList();
> >     Constructor constructor = clazz.getConstructor(new Class[]
> > {List.class});
> >     Object o = constructor.newInstance(new Object[] {list});
> >     if (o instanceof TestSuperClass)
> >     {
> >       ((TestSuperClass) o).add("foo");
> >       assertEquals("length not 1", 1, list.size());
> >       assertEquals("first value not foo", "foo", list.get(0));
> >       list.remove(0);
> >     }
> >     else
> >     {
> >       System.out.println("not TestSuperClass");
> >       System.out.println("clazz.getSuperclass() = " +
> > clazz.getSuperclass());
> >       for (int i = 0; i < clazz.getInterfaces().length; i++)
> >       {
> >         Class aClass = clazz.getInterfaces()[i];
> >         System.out.println("implements " + aClass);
> >       }
> >
> >       System.out.println("-------------");
> >       System.out.println("TestSuperClass.class = " +
> > TestSuperClass.class.getClassLoader());
> >       System.out.println("clazz.getSuperclass() = " +
> > clazz.getSuperclass().getClassLoader());
> >     }
> >
> >     java.lang.reflect.Method method = o.getClass().getMethod("add", new
> > Class[] { Object.class } );
> >     System.out.println("add method = " + method);
> >     method.invoke(o, new Object[] {"foo"});
> >     assertEquals("length not 1", 1, list.size());
> >     assertEquals("first value not foo", "foo", list.get(0));
> >
> > //    dump(className);
> >   }
> >
> >   private void addField(ObjectType ctxType, String ctxFieldName,
> > ConstantPoolGen cp, ClassGen cg)
> >   {
> >     FieldGen fieldGen = new FieldGen(Constants.ACC_PUBLIC, // |
> > Constants.ACC_FINAL,
> >                                      ctxType,
> >                                      ctxFieldName,
> >                                      cp);
> >     Field field = fieldGen.getField();
> >     cg.addField(field);
> >   }
> >
> >   public static void dump(String className, String methodName)
> >   {
> >     JavaClass clazz = Repository.lookupClass(className);
> >     dump(clazz, methodName, className);
> >   }
> >
> >   private static void dump(JavaClass clazz, String methodName, String
> > className)
> >   {
> >     Method[] methods = clazz.getMethods();
> >     for (int i = 0; i < methods.length; i++)
> >     {
> >       Method method = methods[i];
> >       if (methodName != null && !method.getName().equals(methodName))
> >         continue;
> >
> >       System.out.println("method = " + method);
> >       ConstantPoolGen cp = new ConstantPoolGen();
> >       MethodGen methodGen = new MethodGen(method, className, cp);
> >       InstructionList instructionList = methodGen.getInstructionList();
> >       Instruction[] instructions = instructionList.getInstructions();
> >       for (int j = 0; j < instructions.length; j++)
> >       {
> >         Instruction instruction = instructions[j];
> >         System.out.println("instruction = " + instruction);
> >       }
> >
> >       System.out.println("");
> >       System.out.println("-----------------------------------");
> >       System.out.println("");
> >     }
> >   }
> >
> >   private void addConstructor(ClassGen cg, ConstantPoolGen cp, final
> String
> > superClassName, final String className, String ctxFieldName, ObjectType
> > ctxType)
> >   {
> >     InstructionList il = new InstructionList();
> >     InstructionFactory factory = new InstructionFactory(cg, cp);
> >     il.append(new ALOAD(0));
> >     il.append(factory.createInvoke(superClassName, "<init>", Type.VOID,
> new
> > Type[0], Constants.INVOKESPECIAL));
> >     il.append(new ALOAD(0)); // load ctx
> >     il.append(new ALOAD(1)); // load ctx
> >     il.append(factory.createPutField(className, ctxFieldName, ctxType));
> >     il.append(new RETURN());
> >     MethodGen constructorGen = new MethodGen(Constants.ACC_PUBLIC,
> >                                              Type.VOID,
> >                                              new Type[]{ctxType},
> >                                              new String[]{"list"},
> >                                              "<init>",
> >                                              className,
> >                                              il,
> >                                              cp);
> >     constructorGen.setMaxStack();
> >     cg.addMethod(constructorGen.getMethod());
> >
> >     il.dispose();
> >   }
> >
> >
> >   private void addMethod(ClassGen cg, ConstantPoolGen cp, String
> className,
> > String ctxFieldName, ObjectType ctxType)
> >   {
> > //    generated:
> > //    method = public void add(Object o)
> > //    instruction = aload_0[42](1)
> > //    instruction = getfield[180](3) 14
> > //    instruction = aload_1[43](1)
> > //    instruction = invokeinterface[185](5) 25
> > //    instruction = pop[87](1)
> > //    instruction = return[177](1)
> > //
> > //    -----------------------------------
> > //
> > //    coded:
> > //    method = public void add(Object o)
> > //    instruction = aload_0[42](1)
> > //    instruction = getfield[180](3) 109
> > //    instruction = aload_1[43](1)
> > //    instruction = invokeinterface[185](5) 110
> > //    instruction = pop[87](1)
> > //    instruction = return[177](1)
> >
> >     InstructionList il = new InstructionList();
> >     InstructionFactory factory = new InstructionFactory(cg, cp);
> >     il.append(new ALOAD(0));
> >     il.append(factory.createGetField(className, ctxFieldName, ctxType));
> >     il.append(new ALOAD(1));
> >     il.append(factory.createInvoke("java.util.List", "add", Type.VOID,
new
> > Type[] {Type.OBJECT}, Constants.INVOKEINTERFACE));
> > //    il.append(new POP());
> >     il.append(new RETURN());
> >     MethodGen mg = new MethodGen(Constants.ACC_PUBLIC,
> >                                              Type.VOID,
> >                                              new Type[] {Type.OBJECT},
> >                                              new String[]{"o"},
> >                                              "add",
> >                                              className,
> >                                              il,
> >                                              cp);
> >     mg.setMaxStack();
> >     cg.addMethod(mg.getMethod());
> >
> >     il.dispose();
> >   }
> >
> > }
> >
> >
> > package com.colebatch;
> >
> > public abstract class TestSuperClass
> > {
> >   public TestSuperClass()
> >   {
> >     System.out.println("TestSuperClass.<init>()");
> >   }
> >
> >   public abstract void add(Object o);
> > }
> >
> >
> > --
> > To unsubscribe, e-mail:
> <ma...@jakarta.apache.org>
> > For additional commands, e-mail:
> <ma...@jakarta.apache.org>
> >
> >
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: two questions: classloading, and NoSuchMethodFoundErrors on on-the-fly generated classes

Posted by Dmitri Colebatch <di...@bigpond.net.au>.
Further to the below, if I override modifyClass to return null I fix the
casting problem, but that then goes back to the same NoClassdefFoundError
looking for the method that I think is there (o:

again, be greatful for any assistance.

cheers
dim

----- Original Message -----
From: "Dmitri Colebatch" <di...@colebatch.com>
To: <bc...@jakarta.apache.org>
Sent: Monday, October 14, 2002 1:05 AM
Subject: two questions: classloading, and NoSuchMethodFoundErrors on
on-the-fly generated classes


> Hey all,
>
> I'm hoping this isn't too much of a newbie post - I have done a search
> through the archives, and read the manual... if there's something else I
> should have looked at before writing this, then please point me there (o:
>
> First things first.  My requirements are to dynamically implement an
> abstract class.  The test case I have (see end of email for my hacky src
> code) is one where I create a class, and then load it using my classloader
> (subclasses bcel.util.ClassLoader), and then two tests - try to call a
> method through reflection, and try to cast it to the superclass.
>
> reflection does all sorts of weird things:
>
> add method = public void
> com.colebatch.$$BCEL$$GeneratedObject.add(java.lang.Object)
> java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodError
>  at com.colebatch.$$BCEL$$GeneratedObject.add(<generated>)
>
> which comes from this bit of code:
>
>     java.lang.reflect.Method method = o.getClass().getMethod("add", new
> Class[] { Object.class } );
>     System.out.println("add method = " + method);
>     method.invoke(o, new Object[] {"foo"});
>
> which I find _really_ weird, I would have expected getMethod(..) line to
> fail, but we get passed that, and then apparently the method doesn't
exist.
>
> casting behaves a little more understandably.... in that, it does't cast.
> Simple though, because the superclass is loaded by two different class
> loaders:
>
> TestSuperClass.class = sun.misc.Launcher$AppClassLoader@71732b
> clazz.getSuperclass() = com.colebatch.TestBCEL$1@70eed6
>
> (from code:)
>
>       System.out.println("TestSuperClass.class = " +
> TestSuperClass.class.getClassLoader());
>       System.out.println("clazz.getSuperclass() = " +
> clazz.getSuperclass().getClassLoader());
>
> I assume what happes here is that the bcel classloader loads the child
> class, and all its superclasses....  looking through the code, modifyClass
> (whilst not doing anything) ensures that the class is loaded by the bcel
cl.
> Am I being naive/stupid thinking that I can use on-the-fly generated
classes
> without using JavaWrapper?  At this stage there's no real reason why I
> couldn't use it, but I'd prefer to be as hands-off as I can be at this
> point.
>
> any feedback on either of the above issues would be greatly appreciated.
>
> cheers
> dim
>
> ------------------- src code here -----------------
>
> package com.colebatch;
>
> import junit.framework.Test;
> import junit.framework.TestCase;
> import junit.framework.TestSuite;
> import org.apache.bcel.Constants;
> import org.apache.bcel.Repository;
> import org.apache.bcel.classfile.ClassParser;
> import org.apache.bcel.classfile.ConstantClass;
> import org.apache.bcel.classfile.ConstantPool;
> import org.apache.bcel.classfile.ConstantUtf8;
> import org.apache.bcel.classfile.Field;
> import org.apache.bcel.classfile.JavaClass;
> import org.apache.bcel.classfile.Method;
> import org.apache.bcel.generic.ALOAD;
> import org.apache.bcel.generic.ClassGen;
> import org.apache.bcel.generic.ConstantPoolGen;
> import org.apache.bcel.generic.FieldGen;
> import org.apache.bcel.generic.Instruction;
> import org.apache.bcel.generic.InstructionFactory;
> import org.apache.bcel.generic.InstructionList;
> import org.apache.bcel.generic.MethodGen;
> import org.apache.bcel.generic.ObjectType;
> import org.apache.bcel.generic.RETURN;
> import org.apache.bcel.generic.Type;
>
> import java.io.ByteArrayInputStream;
> import java.io.ByteArrayOutputStream;
> import java.io.IOException;
> import java.lang.reflect.Constructor;
> import java.util.ArrayList;
> import java.util.HashMap;
> import java.util.List;
> import java.util.Map;
>
> public class TestBCEL extends TestCase implements Constants
> {
>   public TestBCEL(String name)
>   {
>     super(name);
>   }
>
>   public static Test suite()
>   {
>     return new TestSuite(TestBCEL.class);
>   }
>
>   public static void main(String[] args) throws Exception
>   {
>     new TestBCEL("foo").testBCEL();
>   }
>
>
>
//-------------------------------------------------------------------------
>   // tests
>
>   public void testBCEL()
>     throws Exception
>   {
>     final String superClassName = "com.colebatch.TestSuperClass";
>     final String className = "com.colebatch.$$BCEL$$GeneratedObject";
>
>     ClassGen cg = new ClassGen(className, superClassName,
>                                "<generated>", ACC_PUBLIC | ACC_SUPER,
>                                null);
>     ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool
>
>     String ctxFieldName = "list";
>     ObjectType ctxType = new ObjectType("java.util.List");
>
>     addField(ctxType, ctxFieldName, cp, cg);
>     addConstructor(cg, cp, superClassName, className, ctxFieldName,
> ctxType);
>     addMethod(cg, cp, className, ctxFieldName, ctxType);
>
>     final Map classes = new HashMap();
>
>     ByteArrayOutputStream baos = new ByteArrayOutputStream();
>     cg.getJavaClass().dump(baos);
>     classes.put(className, baos.toByteArray());
>
>     org.apache.bcel.util.ClassLoader cl = new
> org.apache.bcel.util.ClassLoader()
>     {
>       protected JavaClass createClass(String class_name)
>       {
>         byte[]      bytes  = (byte[]) classes.get(class_name);
>         ClassParser parser = new ClassParser(new
> ByteArrayInputStream(bytes), "<generated>");
>
>         JavaClass clazz = null;
>
>         try
>         {
>           clazz = parser.parse();
>
>           dump(clazz, null, class_name);
>
>           // Adapt the class name to the passed value
>           ConstantPool cp = clazz.getConstantPool();
>
>           ConstantClass cl =
> (ConstantClass)cp.getConstant(clazz.getClassNameIndex(),
>                        Constants.CONSTANT_Class);
>           ConstantUtf8 name =
> (ConstantUtf8)cp.getConstant(cl.getNameIndex(),
>                        Constants.CONSTANT_Utf8);
>           name.setBytes(class_name.replace('.', '/'));
>
>           return clazz;
>         }
>         catch (IOException e)
>         {
>           throw new RuntimeException(e.getMessage());
>         }
>       }
>     };
>     Class clazz = cl.loadClass(className);
>
>     for (int i = 0; i < clazz.getMethods().length; i++)
>     {
>       java.lang.reflect.Method method = clazz.getMethods()[i];
>       System.out.println("method = " + method);
>     }
>
>     List list = new ArrayList();
>     Constructor constructor = clazz.getConstructor(new Class[]
> {List.class});
>     Object o = constructor.newInstance(new Object[] {list});
>     if (o instanceof TestSuperClass)
>     {
>       ((TestSuperClass) o).add("foo");
>       assertEquals("length not 1", 1, list.size());
>       assertEquals("first value not foo", "foo", list.get(0));
>       list.remove(0);
>     }
>     else
>     {
>       System.out.println("not TestSuperClass");
>       System.out.println("clazz.getSuperclass() = " +
> clazz.getSuperclass());
>       for (int i = 0; i < clazz.getInterfaces().length; i++)
>       {
>         Class aClass = clazz.getInterfaces()[i];
>         System.out.println("implements " + aClass);
>       }
>
>       System.out.println("-------------");
>       System.out.println("TestSuperClass.class = " +
> TestSuperClass.class.getClassLoader());
>       System.out.println("clazz.getSuperclass() = " +
> clazz.getSuperclass().getClassLoader());
>     }
>
>     java.lang.reflect.Method method = o.getClass().getMethod("add", new
> Class[] { Object.class } );
>     System.out.println("add method = " + method);
>     method.invoke(o, new Object[] {"foo"});
>     assertEquals("length not 1", 1, list.size());
>     assertEquals("first value not foo", "foo", list.get(0));
>
> //    dump(className);
>   }
>
>   private void addField(ObjectType ctxType, String ctxFieldName,
> ConstantPoolGen cp, ClassGen cg)
>   {
>     FieldGen fieldGen = new FieldGen(Constants.ACC_PUBLIC, // |
> Constants.ACC_FINAL,
>                                      ctxType,
>                                      ctxFieldName,
>                                      cp);
>     Field field = fieldGen.getField();
>     cg.addField(field);
>   }
>
>   public static void dump(String className, String methodName)
>   {
>     JavaClass clazz = Repository.lookupClass(className);
>     dump(clazz, methodName, className);
>   }
>
>   private static void dump(JavaClass clazz, String methodName, String
> className)
>   {
>     Method[] methods = clazz.getMethods();
>     for (int i = 0; i < methods.length; i++)
>     {
>       Method method = methods[i];
>       if (methodName != null && !method.getName().equals(methodName))
>         continue;
>
>       System.out.println("method = " + method);
>       ConstantPoolGen cp = new ConstantPoolGen();
>       MethodGen methodGen = new MethodGen(method, className, cp);
>       InstructionList instructionList = methodGen.getInstructionList();
>       Instruction[] instructions = instructionList.getInstructions();
>       for (int j = 0; j < instructions.length; j++)
>       {
>         Instruction instruction = instructions[j];
>         System.out.println("instruction = " + instruction);
>       }
>
>       System.out.println("");
>       System.out.println("-----------------------------------");
>       System.out.println("");
>     }
>   }
>
>   private void addConstructor(ClassGen cg, ConstantPoolGen cp, final
String
> superClassName, final String className, String ctxFieldName, ObjectType
> ctxType)
>   {
>     InstructionList il = new InstructionList();
>     InstructionFactory factory = new InstructionFactory(cg, cp);
>     il.append(new ALOAD(0));
>     il.append(factory.createInvoke(superClassName, "<init>", Type.VOID,
new
> Type[0], Constants.INVOKESPECIAL));
>     il.append(new ALOAD(0)); // load ctx
>     il.append(new ALOAD(1)); // load ctx
>     il.append(factory.createPutField(className, ctxFieldName, ctxType));
>     il.append(new RETURN());
>     MethodGen constructorGen = new MethodGen(Constants.ACC_PUBLIC,
>                                              Type.VOID,
>                                              new Type[]{ctxType},
>                                              new String[]{"list"},
>                                              "<init>",
>                                              className,
>                                              il,
>                                              cp);
>     constructorGen.setMaxStack();
>     cg.addMethod(constructorGen.getMethod());
>
>     il.dispose();
>   }
>
>
>   private void addMethod(ClassGen cg, ConstantPoolGen cp, String
className,
> String ctxFieldName, ObjectType ctxType)
>   {
> //    generated:
> //    method = public void add(Object o)
> //    instruction = aload_0[42](1)
> //    instruction = getfield[180](3) 14
> //    instruction = aload_1[43](1)
> //    instruction = invokeinterface[185](5) 25
> //    instruction = pop[87](1)
> //    instruction = return[177](1)
> //
> //    -----------------------------------
> //
> //    coded:
> //    method = public void add(Object o)
> //    instruction = aload_0[42](1)
> //    instruction = getfield[180](3) 109
> //    instruction = aload_1[43](1)
> //    instruction = invokeinterface[185](5) 110
> //    instruction = pop[87](1)
> //    instruction = return[177](1)
>
>     InstructionList il = new InstructionList();
>     InstructionFactory factory = new InstructionFactory(cg, cp);
>     il.append(new ALOAD(0));
>     il.append(factory.createGetField(className, ctxFieldName, ctxType));
>     il.append(new ALOAD(1));
>     il.append(factory.createInvoke("java.util.List", "add", Type.VOID, new
> Type[] {Type.OBJECT}, Constants.INVOKEINTERFACE));
> //    il.append(new POP());
>     il.append(new RETURN());
>     MethodGen mg = new MethodGen(Constants.ACC_PUBLIC,
>                                              Type.VOID,
>                                              new Type[] {Type.OBJECT},
>                                              new String[]{"o"},
>                                              "add",
>                                              className,
>                                              il,
>                                              cp);
>     mg.setMaxStack();
>     cg.addMethod(mg.getMethod());
>
>     il.dispose();
>   }
>
> }
>
>
> package com.colebatch;
>
> public abstract class TestSuperClass
> {
>   public TestSuperClass()
>   {
>     System.out.println("TestSuperClass.<init>()");
>   }
>
>   public abstract void add(Object o);
> }
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>
>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>