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" <[EMAIL PROTECTED]> To: "BCEL Users List" <[EMAIL PROTECTED]> 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" <[EMAIL PROTECTED]> > > To: <[EMAIL PROTECTED]> > > 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: > > <mailto:[EMAIL PROTECTED]> > > > For additional commands, e-mail: > > <mailto:[EMAIL PROTECTED]> > > > > > > > > > > > > -- > > To unsubscribe, e-mail: > <mailto:[EMAIL PROTECTED]> > > For additional commands, e-mail: > <mailto:[EMAIL PROTECTED]> > > > > > -- > To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> > For additional commands, e-mail: <mailto:[EMAIL PROTECTED]> > -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
