Java动态性的两种常见实现方式java
运行时操做字节码能够让咱们实现以下功能:git
优点:github
常见的字节码操做类库express
BCEL数组
这是Apache Software Fundation的jakarta项目的一部分。BCEL是javaclassworking普遍使用的一种跨级啊,它能够让你深刻JVM汇编语言进行类的操做的细节。BCEL与javassist所强调的是源码级别的工做。app
ASM框架
是一个轻量及java字节码操做框架,直接涉及到JVM底层的操做和指令。ide
CGLIB工具
是一个强大的,高性能,高质量的Code生成类库,基于ASM实现。性能
JAVAssist
JAVAssist库的API
官方介绍:
Javassist (Java Programming Assistant) makes Java bytecode manipulation simple. It is a class library for editing bytecodes in Java; it enables Java programs to define a new class at runtime and to modify a class file when the JVM loads it. Unlike other similar bytecode editors, Javassist provides two levels of API: source level and bytecode level. If the users use the source-level API, they can edit a class file without knowledge of the specifications of the Java bytecode. The whole API is designed with only the vocabulary of the Java language. You can even specify inserted bytecode in the form of source text; Javassist compiles it on the fly. On the other hand, the bytecode-level API allows the users to directly edit a class file as other editors.
javassist库的简单使用
例1:
public class Demo01 { public static void main(String[] args) throws Exception { ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.makeClass("com.bjsxt.bean.Emp"); //建立属性 CtField f1 = CtField.make("private int empno;", cc); CtField f2 = CtField.make("private String ename;", cc); cc.addField(f1); cc.addField(f2); //建立方法 CtMethod m1 = CtMethod.make("public int getEmpno(){return empno;}", cc); CtMethod m2 = CtMethod.make("public void setEmpno(int empno){this.empno=empno;}", cc); cc.addMethod(m1); cc.addMethod(m2); //添加构造器 CtConstructor constructor = new CtConstructor(new CtClass[]{CtClass.intType,pool.get("java.lang.String")}, cc); constructor.setBody("{this.empno=empno; this.ename=ename;}"); cc.addConstructor(constructor); cc.writeFile("c:/myjava"); //将上面构造好的类写入到c:/myjava中 System.out.println("生成类,成功!"); } }
javassist库的API
各类符号替代:
$0, $1, $2, ... |
this and actual parameters |
$args |
An array of parameters. The type of $args is Object[]. |
$$ |
All actual parameters. For example, m($$) is equivalent to m($1,$2,...) |
$cflow(...) |
cflow variable |
$r |
The result type. It is used in a cast expression. |
$w |
The wrapper type. It is used in a cast expression. |
$_ |
The resulting value |
$sig |
An array of java.lang.Class objects representing the formal parameter types. |
$type |
A java.lang.Class object representing the formal result type. |
$class |
A java.lang.Class object representing the class currently edited. |
例2:
public class Demo02 { /** * 处理类的基本用法 * @throws Exception */ public static void test01() throws Exception{ ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("com.sinosoft.test.Emp"); byte[] bytes = cc.toBytecode(); System.out.println(Arrays.toString(bytes)); System.out.println(cc.getName()); //获取类名 System.out.println(cc.getSimpleName()); //获取简要类名 System.out.println(cc.getSuperclass()); //得到父类 System.out.println(cc.getInterfaces()); //得到接口 } /** * 测试产生新的方法 * @throws Exception */ public static void test02() throws Exception{ ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("com.bjsxt.test.Emp"); // CtMethod m = CtNewMethod.make("public int add(int a,int b){return a+b;}", cc); CtMethod m = new CtMethod(CtClass.intType,"add", new CtClass[]{CtClass.intType,CtClass.intType},cc); m.setModifiers(Modifier.PUBLIC); m.setBody("{System.out.println(\"Hello!!!\");return $1+$2;}"); cc.addMethod(m); //经过反射调用新生成的方法 Class clazz = cc.toClass(); Object obj = clazz.newInstance(); //经过调用Emp无参构造器,建立新的Emp对象 Method method = clazz.getDeclaredMethod("add", int.class,int.class); Object result = method.invoke(obj, 200,300); System.out.println(result); } /** * 修改已有的方法的信息,修改方法体的内容 * @throws Exception */ public static void test03() throws Exception{ ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("com.sinosoft.test.Emp"); CtMethod cm = cc.getDeclaredMethod("sayHello",new CtClass[]{CtClass.intType}); //方法执行前 cm.insertBefore("System.out.println($1);System.out.println(\"start!!!\");"); cm.insertAt(9, "int b=3;System.out.println(\"b=\"+b);"); //方法执行后 cm.insertAfter("System.out.println(\"after!!!\");"); //经过反射调用新生成的方法 Class clazz = cc.toClass(); Object obj = clazz.newInstance(); //经过调用Emp无参构造器,建立新的Emp对象 Method method = clazz.getDeclaredMethod("sayHello", int.class); method.invoke(obj, 300); } /** * 属性的操做 * @throws Exception */ public static void test04() throws Exception{ ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("com.sinosoft.test.Emp"); // CtField f1 = CtField.make("private int empno;", cc); CtField f1 = new CtField(CtClass.intType,"salary",cc); f1.setModifiers(Modifier.PRIVATE); cc.addField(f1); // cc.getDeclaredField("ename"); //获取指定的属性 //增长相应的set和get方法 cc.addMethod(CtNewMethod.getter("getSalary", f1));; cc.addMethod(CtNewMethod.getter("setSalary", f1));; } /** * 构造方法的操做 * @throws Exception */ public static void test05() throws Exception { ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("com.sinosoft.test.Emp"); CtConstructor[] cs = cc.getConstructors(); for (CtConstructor c : cs) { System.out.println(c.getLongName()); } } /** * 注解操做 * @throws Exception */ public static void test06() throws Exception{ CtClass cc = ClassPool.getDefault().get("com.sinosoft.test.Emp"); Object[] all = cc.getAnnotations(); Author a = (Author)all[0]; String name = a.name(); int year = a.year(); System.out.println("name: " + name + ", year: " + year); } public static void main(String[] args) throws Exception { test06(); } } /** * 注解类 * */ public @interface Author { String name(); int year(); }
局限性:
class A{} class extends A{} class C extends B{}