javassist学习三
来源:互联网 发布:离线搜题软件 编辑:程序博客网 时间:2024/05/21 03:20
这里举个简单的例子,来记录下如何用CtClass创建一个类,并且往这个类里面新加方法,
下面是代码,可以直接运行:
- package seeeyou.app.test;
- import java.io.IOException;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import javassist.CannotCompileException;
- import javassist.ClassPool;
- import javassist.CtClass;
- import javassist.CtMethod;
- import javassist.CtNewMethod;
- import javassist.NotFoundException;
- /**
- *
- * @author seeeyou
- *
- */
- public class TestHelloWorld2 {
- public static void main(String[] args) throws NotFoundException,
- IOException, CannotCompileException, InstantiationException,
- IllegalAccessException, SecurityException, NoSuchMethodException,
- IllegalArgumentException, InvocationTargetException {
- // 用于取得字节码类,必须在当前的classpath中,使用全称
- ClassPool pool = ClassPool.getDefault();
- /**
- * makeClass() cannot create a new interface; makeInterface() in
- * ClassPool can do. Member methods in an interface can be created with
- * abstractMethod() in CtNewMethod. Note that an interface method is an
- * abstract method.
- */
- CtClass ccClass = pool.makeClass("Point");
- String bodyString = "{System.out.println(\"Call to method \");}";
- //为新创建的类新加一个方法execute,无任何参数
- CtMethod n1 = CtNewMethod.make(CtClass.voidType, "execute", null, null,
- bodyString, ccClass);
- ccClass.addMethod(n1);
- /**
- * 这里无法用new的形式来创建一个对象,因为已经classloader中不能有两个相同的对象,否则会报异常如下:
- *Caused by: java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader):
- *attempted duplicate class definition for name: "Point"
- **/
- Object oo = ccClass.toClass().newInstance();
- Method mms = oo.getClass().getMethod("execute", null);
- System.out.println("new class name is : " + oo.getClass().getName());
- System.out.println("new class's method is : " + mms.invoke(oo, null));
- System.out.println("---------------------------------------------");
- //这一行代码将class冻结了,下面无法再对类多编辑或者修改,下面的setName会报异常如:
- //Exception in thread "main" java.lang.RuntimeException: Point class is frozen
- ccClass.freeze();
- try{
- ccClass.setName("Point2");
- }catch (Exception e) {
- System.out.println(e);
- }
- //对已经冻结的class解冻之后还可以继续编辑修改
- ccClass.defrost();
- <span style="color: #ff0000;"> System.out.println("------------- 上面的代码是对的,下面的代码将会无法执行出结果,会报错------------------------");</span>
- //第二个方法
- bodyString = "public int getNumber(Integer num){System.out.println(\"Point2 Call to method \");return 10+num;}";
- CtMethod n2 = CtNewMethod.make(bodyString, ccClass);//直接创建一个方法,带有一个int的参数和返回值
- ccClass.addMethod(n2);
- Class[] params = new Class[1];
- Integer num = new Integer(15);
- params[0] = num.getClass();
- mms = oo.getClass().getMethod("getNumber", params);
- System.out.println("new class name is : " + oo.getClass().getName());
- System.out.println("new class's method is : " + mms.invoke(oo, 100));
- System.out.println("---------------------------------------------");
- }
- }
- 上面的结果是:new class name is : Point
- Call to method
- new class's method is : null
- ---------------------------------------------
- java.lang.RuntimeException: Point class is frozen
- ---------------------------------------------
- Exception in thread "main" java.lang.NoSuchMethodException: Point.getNumber(java.lang.Integer)
- at java.lang.Class.getMethod(Class.java:1605)
- at seeeyou.app.test.TestHelloWorld2.main(TestHelloWorld2.java:66)
错误的原因其实和简单,因为我第二次新加一个方法后,没有再次实例化一个对象,所以oo还是原来的对象,他的成员函数肯定没有新加的方法。
那我可以再次实例化下试试,代码和结果如下:
- package seeeyou.app.test;
- import java.io.IOException;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import javassist.CannotCompileException;
- import javassist.ClassPool;
- import javassist.CtClass;
- import javassist.CtMethod;
- import javassist.CtNewMethod;
- import javassist.NotFoundException;
- /**
- *
- * @author seeeyou
- *
- */
- public class TestHelloWorld2 {
- public static void main(String[] args) throws NotFoundException,
- IOException, CannotCompileException, InstantiationException,
- IllegalAccessException, SecurityException, NoSuchMethodException,
- IllegalArgumentException, InvocationTargetException {
- // 用于取得字节码类,必须在当前的classpath中,使用全称
- ClassPool pool = ClassPool.getDefault();
- /**
- * makeClass() cannot create a new interface; makeInterface() in
- * ClassPool can do. Member methods in an interface can be created with
- * abstractMethod() in CtNewMethod. Note that an interface method is an
- * abstract method.
- */
- CtClass ccClass = pool.makeClass("Point");
- String bodyString = "{System.out.println(\"Call to method \");}";
- //为新创建的类新加一个方法execute,无任何参数
- CtMethod n1 = CtNewMethod.make(CtClass.voidType, "execute", null, null,
- bodyString, ccClass);
- ccClass.addMethod(n1);
- /**
- * 这里无法用new的形式来创建一个对象,因为已经classloader中不能有两个相同的对象,否则会报异常如下:
- *Caused by: java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader):
- *attempted duplicate class definition for name: "Point"
- **/
- Object oo = ccClass.toClass().newInstance();
- Method mms = oo.getClass().getMethod("execute", null);
- System.out.println("new class name is : " + oo.getClass().getName());
- System.out.println("new class's method is : " + mms.invoke(oo, null));
- System.out.println("---------------------------------------------");
- //这一行代码将class冻结了,下面无法再对类多编辑或者修改,下面的setName会报异常如:
- //Exception in thread "main" java.lang.RuntimeException: Point class is frozen
- ccClass.freeze();
- try{
- ccClass.setName("Point2");
- }catch (Exception e) {
- System.out.println(e);
- }
- //对已经冻结的class解冻之后还可以继续编辑修改
- ccClass.defrost();
- System.out.println("------------- 上面的代码是对的,下面的代码将会无法执行出结果,会报错------------------------");
- //第二个方法
- bodyString = "public int getNumber(Integer num){System.out.println(\"Point2 Call to method \");return 10+num;}";
- CtMethod n2 = CtNewMethod.make(bodyString, ccClass);//直接创建一个方法,带有一个int的参数和返回值
- ccClass.addMethod(n2);
- Class[] params = new Class[1];
- Integer num = new Integer(15);
- params[0] = num.getClass();//就多了下面这个实例化,但是这样会导致一个错误
- oo = ccClass.toClass().newInstance();
- mms = oo.getClass().getMethod("getNumber", params);
- System.out.println("new class name is : " + oo.getClass().getName());
- System.out.println("new class's method is : " + mms.invoke(oo, 100));
- System.out.println("---------------------------------------------");
- }
- }
- 这也会导致一个错误:new class name is : Point
- Call to method
- new class's method is : null
- ---------------------------------------------
- java.lang.RuntimeException: Point class is frozen
- ------------- 上面的代码是对的,下面的代码将会无法执行出结果,会报错------------------------
- Exception in thread "main" javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "Point"
- at javassist.ClassPool.toClass(ClassPool.java:1051)
- at javassist.ClassPool.toClass(ClassPool.java:994)
- at javassist.ClassPool.toClass(ClassPool.java:952)
- at javassist.CtClass.toClass(CtClass.java:1079)
- at seeeyou.app.test.TestHelloWorld2.main(TestHelloWorld2.java:66)
- Caused by: java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "Point"
- at java.lang.ClassLoader.defineClass1(Native Method)
- at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
- at java.lang.ClassLoader.defineClass(ClassLoader.java:466)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at javassist.ClassPool.toClass2(ClassPool.java:1063)
- at javassist.ClassPool.toClass(ClassPool.java:1045)
- ... 4 more
- 原因也很简单,一个classloader里面怎么有两个重复的对象呢,除非是两个不同的classloader。。所以爆了个重复加载类的错误
对的方式是只实例化一次:如下:
- package seeeyou.app.test;
- import java.io.IOException;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import javassist.CannotCompileException;
- import javassist.ClassPool;
- import javassist.CtClass;
- import javassist.CtMethod;
- import javassist.CtNewMethod;
- import javassist.NotFoundException;
- /**
- *
- * @author seeeyou
- *
- */
- public class TestHelloWorld3 {
- public static void main(String[] args) throws NotFoundException,
- IOException, CannotCompileException, InstantiationException,
- IllegalAccessException, SecurityException, NoSuchMethodException,
- IllegalArgumentException, InvocationTargetException {
- // 用于取得字节码类,必须在当前的classpath中,使用全称
- ClassPool pool = ClassPool.getDefault();
- /**
- * makeClass() cannot create a new interface; makeInterface() in
- * ClassPool can do. Member methods in an interface can be created with
- * abstractMethod() in CtNewMethod. Note that an interface method is an
- * abstract method.
- */
- CtClass ccClass = pool.makeClass("Point");
- String bodyString = "{System.out.println(\"Call to method \");}";
- //为新创建的类新加一个方法execute,无任何参数
- CtMethod n1 = CtNewMethod.make(CtClass.voidType, "execute", null, null,
- bodyString, ccClass);
- ccClass.addMethod(n1);
- //新加第二个方法
- bodyString = "public Integer getNumber(Integer num);";
- CtMethod n2 = CtNewMethod.make(bodyString, ccClass);//直接创建一个方法,带有一个int的参数和返回值
- n2.setBody("{System.out.println(\"Point Call to method \");return $1;}");
- ccClass.addMethod(n2);
- /**
- * 这里无法用new的形式来创建一个对象,因为已经classloader中不能有两个相同的对象,否则会报异常如下:
- *Caused by: java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader):
- *attempted duplicate class definition for name: "Point"
- **/
- Object oo = ccClass.toClass().newInstance();
- Method mms = oo.getClass().getMethod("execute", null);
- System.out.println("new class name is : " + oo.getClass().getName());
- System.out.println("new class's method is : " + mms.invoke(oo, null));
- System.out.println("---------------------------------------------");
- //这一行代码将class冻结了,下面无法再对类多编辑或者修改,下面的setName会报异常如:
- //Exception in thread "main" java.lang.RuntimeException: Point class is frozen
- ccClass.freeze();
- try{
- ccClass.setName("Point2");
- }catch (Exception e) {
- System.out.println(e);
- }
- //对已经冻结的class解冻之后还可以继续编辑修改
- ccClass.defrost();
- System.out.println("------------- 上面的代码是对的,下面的代码将会无法执行出结果,会报错------------------------");
- Class[] params = new Class[1];
- Integer num = new Integer(0);
- params[0] = num.getClass();
- mms = oo.getClass().getMethod("getNumber",params);
- System.out.println("new class name is : " + oo.getClass().getName());
- System.out.println("new class's method is : " + mms.invoke(oo, 100));
- System.out.println("---------------------------------------------");
- }
- }
- 结果如下:new class name is : Point
- Call to method
- new class's method is : null
- ---------------------------------------------
- java.lang.RuntimeException: Point class is frozen
- ------------- 上面的代码是对的,下面的代码将会无法执行出结果,会报错------------------------
- new class name is : Point
- Point2 Call to method
- new class's method is : 100
- ---------------------------------------------
0 0
- javassist学习三
- javassist学习
- 三.javassist实现代理
- javassist学习笔记
- Javassist学习总结
- javassist 学习笔记
- Javassist学习1:简介
- Javassist学习总结
- javassist 学习笔记
- Javassist学习总结
- Javassist 学习笔记1
- Javassist 学习笔记2
- javassist学习二
- javassist学习一
- Javassist学习总结
- javassist 初步学习
- Javassist学习总结
- javassist 学习笔记
- 解决VirtualBox下安装虚拟机(Ubuntu)出错(不能为虚拟电脑Ubuntu打开一个新的任务)的问题
- Delete Node in a Linked List
- MYSQL之表分区----按日期分区
- HDU 1028 Ignatius and the Princess III
- ruby调用shell问题——找不到自己环境变量中的程序
- javassist学习三
- CodeChef COUNTARI Arithmetic Progressions FFT + 分块
- Objective-C 属性特性详解
- APP源码分享-你最美源码
- ubuntu14.04 64位 adb配置问题
- 连接数据库报“You have an error in your SQL syntax”异常的解决
- Quarzt 2D 裁剪
- 控制器添加控制器的view的方法
- Arrays.binarySearch();