javassist学习三

来源:互联网 发布:离线搜题软件 编辑:程序博客网 时间:2024/05/21 03:20

这里举个简单的例子,来记录下如何用CtClass创建一个类,并且往这个类里面新加方法,

下面是代码,可以直接运行:

Java代码  收藏代码
  1. package seeeyou.app.test;  
  2.   
  3. import java.io.IOException;  
  4. import java.lang.reflect.InvocationTargetException;  
  5. import java.lang.reflect.Method;  
  6.   
  7. import javassist.CannotCompileException;  
  8. import javassist.ClassPool;  
  9. import javassist.CtClass;  
  10. import javassist.CtMethod;  
  11. import javassist.CtNewMethod;  
  12. import javassist.NotFoundException;  
  13.   
  14. /** 
  15.  *  
  16.  * @author seeeyou 
  17.  *  
  18.  */  
  19. public class TestHelloWorld2 {  
  20.     public static void main(String[] args) throws NotFoundException,  
  21.             IOException, CannotCompileException, InstantiationException,  
  22.             IllegalAccessException, SecurityException, NoSuchMethodException,  
  23.             IllegalArgumentException, InvocationTargetException {  
  24.         // 用于取得字节码类,必须在当前的classpath中,使用全称  
  25.         ClassPool pool = ClassPool.getDefault();  
  26.         /** 
  27.          * makeClass() cannot create a new interface; makeInterface() in 
  28.          * ClassPool can do. Member methods in an interface can be created with 
  29.          * abstractMethod() in CtNewMethod. Note that an interface method is an 
  30.          * abstract method. 
  31.          */  
  32.         CtClass ccClass = pool.makeClass("Point");  
  33.         String bodyString = "{System.out.println(\"Call to method \");}";  
  34.         //为新创建的类新加一个方法execute,无任何参数  
  35.         CtMethod n1 = CtNewMethod.make(CtClass.voidType, "execute"nullnull,  
  36.                 bodyString, ccClass);  
  37.         ccClass.addMethod(n1);  
  38.         /** 
  39.          * 这里无法用new的形式来创建一个对象,因为已经classloader中不能有两个相同的对象,否则会报异常如下: 
  40.         *Caused by: java.lang.LinkageError: loader (instance of  sun/misc/Launcher$AppClassLoader):  
  41.         *attempted  duplicate class definition for name: "Point" 
  42.         **/  
  43.         Object oo = ccClass.toClass().newInstance();  
  44.         Method mms = oo.getClass().getMethod("execute"null);  
  45.         System.out.println("new class name is : " + oo.getClass().getName());  
  46.         System.out.println("new class's method is : " + mms.invoke(oo, null));  
  47.         System.out.println("---------------------------------------------");  
  48.         //这一行代码将class冻结了,下面无法再对类多编辑或者修改,下面的setName会报异常如:  
  49.         //Exception in thread "main" java.lang.RuntimeException: Point class is frozen  
  50.         ccClass.freeze();  
  51.         try{  
  52.             ccClass.setName("Point2");  
  53.         }catch (Exception e) {  
  54.             System.out.println(e);  
  55.         }  
  56.         //对已经冻结的class解冻之后还可以继续编辑修改  
  57.          ccClass.defrost();  
  58.         <span style="color: #ff0000;"> System.out.println("------------- 上面的代码是对的,下面的代码将会无法执行出结果,会报错------------------------");</span>  
  59.          //第二个方法  
  60.          bodyString = "public int getNumber(Integer num){System.out.println(\"Point2 Call to method \");return 10+num;}";  
  61.          CtMethod n2 = CtNewMethod.make(bodyString, ccClass);//直接创建一个方法,带有一个int的参数和返回值  
  62.          ccClass.addMethod(n2);  
  63.          Class[] params = new Class[1];  
  64.          Integer num = new Integer(15);  
  65.          params[0] = num.getClass();  
  66.          mms = oo.getClass().getMethod("getNumber", params);  
  67.         System.out.println("new class name is : " + oo.getClass().getName());  
  68.         System.out.println("new class's method is : " + mms.invoke(oo, 100));  
  69.         System.out.println("---------------------------------------------");  
  70.     }  
  71. }  
Java代码  收藏代码
  1. 上面的结果是:new class name is : Point  
  2. Call to method   
  3. new class's method is : null  
  4. ---------------------------------------------  
  5. java.lang.RuntimeException: Point class is frozen  
  6. ---------------------------------------------  
  7. Exception in thread "main" java.lang.NoSuchMethodException: Point.getNumber(java.lang.Integer)  
  8.  at java.lang.Class.getMethod(Class.java:1605)  
  9.  at seeeyou.app.test.TestHelloWorld2.main(TestHelloWorld2.java:66)  

 

错误的原因其实和简单,因为我第二次新加一个方法后,没有再次实例化一个对象,所以oo还是原来的对象,他的成员函数肯定没有新加的方法。

那我可以再次实例化下试试,代码和结果如下:

Java代码  收藏代码
  1. package seeeyou.app.test;  
  2.   
  3. import java.io.IOException;  
  4. import java.lang.reflect.InvocationTargetException;  
  5. import java.lang.reflect.Method;  
  6.   
  7. import javassist.CannotCompileException;  
  8. import javassist.ClassPool;  
  9. import javassist.CtClass;  
  10. import javassist.CtMethod;  
  11. import javassist.CtNewMethod;  
  12. import javassist.NotFoundException;  
  13.   
  14. /** 
  15.  *  
  16.  * @author seeeyou 
  17.  *  
  18.  */  
  19. public class TestHelloWorld2 {  
  20.     public static void main(String[] args) throws NotFoundException,  
  21.             IOException, CannotCompileException, InstantiationException,  
  22.             IllegalAccessException, SecurityException, NoSuchMethodException,  
  23.             IllegalArgumentException, InvocationTargetException {  
  24.         // 用于取得字节码类,必须在当前的classpath中,使用全称  
  25.         ClassPool pool = ClassPool.getDefault();  
  26.         /** 
  27.          * makeClass() cannot create a new interface; makeInterface() in 
  28.          * ClassPool can do. Member methods in an interface can be created with 
  29.          * abstractMethod() in CtNewMethod. Note that an interface method is an 
  30.          * abstract method. 
  31.          */  
  32.         CtClass ccClass = pool.makeClass("Point");  
  33.         String bodyString = "{System.out.println(\"Call to method \");}";  
  34.         //为新创建的类新加一个方法execute,无任何参数  
  35.         CtMethod n1 = CtNewMethod.make(CtClass.voidType, "execute"nullnull,  
  36.                 bodyString, ccClass);  
  37.         ccClass.addMethod(n1);  
  38.         /** 
  39.          * 这里无法用new的形式来创建一个对象,因为已经classloader中不能有两个相同的对象,否则会报异常如下: 
  40.         *Caused by: java.lang.LinkageError: loader (instance of  sun/misc/Launcher$AppClassLoader):  
  41.         *attempted  duplicate class definition for name: "Point" 
  42.         **/  
  43.         Object oo = ccClass.toClass().newInstance();  
  44.         Method mms = oo.getClass().getMethod("execute"null);  
  45.         System.out.println("new class name is : " + oo.getClass().getName());  
  46.         System.out.println("new class's method is : " + mms.invoke(oo, null));  
  47.         System.out.println("---------------------------------------------");  
  48.         //这一行代码将class冻结了,下面无法再对类多编辑或者修改,下面的setName会报异常如:  
  49.         //Exception in thread "main" java.lang.RuntimeException: Point class is frozen  
  50.         ccClass.freeze();  
  51.         try{  
  52.             ccClass.setName("Point2");  
  53.         }catch (Exception e) {  
  54.             System.out.println(e);  
  55.         }  
  56.         //对已经冻结的class解冻之后还可以继续编辑修改  
  57.          ccClass.defrost();  
  58.          System.out.println("------------- 上面的代码是对的,下面的代码将会无法执行出结果,会报错------------------------");  
  59.          //第二个方法  
  60.          bodyString = "public int getNumber(Integer num){System.out.println(\"Point2 Call to method \");return 10+num;}";  
  61.          CtMethod n2 = CtNewMethod.make(bodyString, ccClass);//直接创建一个方法,带有一个int的参数和返回值  
  62.          ccClass.addMethod(n2);  
  63.          Class[] params = new Class[1];  
  64.          Integer num = new Integer(15);  
  65.          params[0] = num.getClass();//就多了下面这个实例化,但是这样会导致一个错误  
  66.          oo = ccClass.toClass().newInstance();  
  67.          mms = oo.getClass().getMethod("getNumber", params);  
  68.         System.out.println("new class name is : " + oo.getClass().getName());  
  69.         System.out.println("new class's method is : " + mms.invoke(oo, 100));  
  70.         System.out.println("---------------------------------------------");  
  71.     }  
  72. }  
Java代码  收藏代码
  1. 这也会导致一个错误:new class name is : Point  
  2. Call to method   
  3. new class's method is : null  
  4. ---------------------------------------------  
  5. java.lang.RuntimeException: Point class is frozen  
  6. ------------- 上面的代码是对的,下面的代码将会无法执行出结果,会报错------------------------  
  7. Exception in thread "main" javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of  sun/misc/Launcher$AppClassLoader): attempted  duplicate class definition for name: "Point"  
  8.  at javassist.ClassPool.toClass(ClassPool.java:1051)  
  9.  at javassist.ClassPool.toClass(ClassPool.java:994)  
  10.  at javassist.ClassPool.toClass(ClassPool.java:952)  
  11.  at javassist.CtClass.toClass(CtClass.java:1079)  
  12.  at seeeyou.app.test.TestHelloWorld2.main(TestHelloWorld2.java:66)  
  13. Caused by: java.lang.LinkageError: loader (instance of  sun/misc/Launcher$AppClassLoader): attempted  duplicate class definition for name: "Point"  
  14.  at java.lang.ClassLoader.defineClass1(Native Method)  
  15.  at java.lang.ClassLoader.defineClass(ClassLoader.java:621)  
  16.  at java.lang.ClassLoader.defineClass(ClassLoader.java:466)  
  17.  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
  18.  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)  
  19.  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)  
  20.  at java.lang.reflect.Method.invoke(Method.java:597)  
  21.  at javassist.ClassPool.toClass2(ClassPool.java:1063)  
  22.  at javassist.ClassPool.toClass(ClassPool.java:1045)  
  23.  ... 4 more  
Java代码  收藏代码
  1. 原因也很简单,一个classloader里面怎么有两个重复的对象呢,除非是两个不同的classloader。。所以爆了个重复加载类的错误  
Java代码  收藏代码
  1.   

 

对的方式是只实例化一次:如下:

Java代码  收藏代码
  1. package seeeyou.app.test;  
  2.   
  3. import java.io.IOException;  
  4. import java.lang.reflect.InvocationTargetException;  
  5. import java.lang.reflect.Method;  
  6.   
  7. import javassist.CannotCompileException;  
  8. import javassist.ClassPool;  
  9. import javassist.CtClass;  
  10. import javassist.CtMethod;  
  11. import javassist.CtNewMethod;  
  12. import javassist.NotFoundException;  
  13.   
  14. /** 
  15.  *  
  16.  * @author seeeyou 
  17.  *  
  18.  */  
  19. public class TestHelloWorld3 {  
  20.   
  21.     public static void main(String[] args) throws NotFoundException,  
  22.             IOException, CannotCompileException, InstantiationException,  
  23.             IllegalAccessException, SecurityException, NoSuchMethodException,  
  24.             IllegalArgumentException, InvocationTargetException {  
  25.         // 用于取得字节码类,必须在当前的classpath中,使用全称  
  26.         ClassPool pool = ClassPool.getDefault();  
  27.         /** 
  28.          * makeClass() cannot create a new interface; makeInterface() in 
  29.          * ClassPool can do. Member methods in an interface can be created with 
  30.          * abstractMethod() in CtNewMethod. Note that an interface method is an 
  31.          * abstract method. 
  32.          */  
  33.         CtClass ccClass = pool.makeClass("Point");  
  34.         String bodyString = "{System.out.println(\"Call to method \");}";  
  35.         //为新创建的类新加一个方法execute,无任何参数  
  36.         CtMethod n1 = CtNewMethod.make(CtClass.voidType, "execute"nullnull,  
  37.                 bodyString, ccClass);  
  38.         ccClass.addMethod(n1);  
  39.         //新加第二个方法  
  40.          bodyString = "public Integer getNumber(Integer num);";  
  41.          CtMethod n2 = CtNewMethod.make(bodyString, ccClass);//直接创建一个方法,带有一个int的参数和返回值  
  42.          n2.setBody("{System.out.println(\"Point Call to method \");return $1;}");  
  43.          ccClass.addMethod(n2);  
  44.   
  45.         /** 
  46.          * 这里无法用new的形式来创建一个对象,因为已经classloader中不能有两个相同的对象,否则会报异常如下: 
  47.         *Caused by: java.lang.LinkageError: loader (instance of  sun/misc/Launcher$AppClassLoader):  
  48.         *attempted  duplicate class definition for name: "Point" 
  49.         **/  
  50.         Object oo = ccClass.toClass().newInstance();  
  51.         Method mms = oo.getClass().getMethod("execute"null);  
  52.         System.out.println("new class name is : " + oo.getClass().getName());  
  53.         System.out.println("new class's method is : " + mms.invoke(oo, null));  
  54.         System.out.println("---------------------------------------------");  
  55.         //这一行代码将class冻结了,下面无法再对类多编辑或者修改,下面的setName会报异常如:  
  56.         //Exception in thread "main" java.lang.RuntimeException: Point class is frozen  
  57.         ccClass.freeze();  
  58.         try{  
  59.             ccClass.setName("Point2");  
  60.         }catch (Exception e) {  
  61.             System.out.println(e);  
  62.         }  
  63.         //对已经冻结的class解冻之后还可以继续编辑修改  
  64.          ccClass.defrost();  
  65.          System.out.println("------------- 上面的代码是对的,下面的代码将会无法执行出结果,会报错------------------------");         
  66.          Class[] params = new Class[1];  
  67.          Integer num = new Integer(0);  
  68.          params[0] = num.getClass();  
  69.          mms = oo.getClass().getMethod("getNumber",params);  
  70.         System.out.println("new class name is : " + oo.getClass().getName());  
  71.         System.out.println("new class's method is : " + mms.invoke(oo, 100));  
  72.         System.out.println("---------------------------------------------");  
  73.     }  
  74. }  
Java代码  收藏代码
  1. 结果如下:new class name is : Point  
  2. Call to method   
  3. new class's method is : null  
  4. ---------------------------------------------  
  5. java.lang.RuntimeException: Point class is frozen  
  6. ------------- 上面的代码是对的,下面的代码将会无法执行出结果,会报错------------------------  
  7. new class name is : Point  
  8. Point2 Call to method   
  9. new class's method is : 100  
  10. ---------------------------------------------  

 

0 0
原创粉丝点击