精华内容
下载资源
问答
  • Java运行时动态生成class的方法

    万次阅读 2016-12-21 18:30:11
    廖雪峰 / 编程 / 4-27 20:45 / 阅读: 2459 Java是一门静态语言,通常,我们需要的class在编译的时候就已经生成了,为什么有时候我们还想在运行时动态生成class呢?

    http://www.liaoxuefeng.com/article/0014617596492474eea2227bf04477e83e6d094683e0536000

    廖雪峰 / 编程 / 4-27 20:45 / 阅读: 2459

    Java是一门静态语言,通常,我们需要的class在编译的时候就已经生成了,为什么有时候我们还想在运行时动态生成class呢?

    因为在有些时候,我们还真得在运行时为一个类动态创建子类。比如,编写一个ORM框架,如何得知一个简单的JavaBean是否被用户修改过呢?

    User为例:

    public class User {
        private String id;
        private String name;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    其实UserProxy实现起来很简单,就是创建一个User的子类,覆写所有setXxx()方法,做个标记就可以了:

    public class UserProxy extends User {
        private boolean dirty;
    
        public boolean isDirty() {
            return this.dirty;
        }
    
        public void setDirty(boolean dirty) {
            this.dirty = dirty;
        }
    
        @Override
        public void setId(String id) {
            super.setId(id);
            setDirty(true);
        }
    
        @Override
        public void setName(String name) {
            super.setName(name);
            setDirty(true);
        }
    }
    

    但是这个UserProxy就必须在运行时动态创建出来了,因为编译时ORM框架根本不知道User类。

    现在问题来了,动态生成字节码,难度有多大?

    如果我们要自己直接输出二进制格式的字节码,在完成这个任务前,必须先认真阅读JVM规范第4章,详细了解class文件结构。估计读完规范后,两个月过去了。

    所以,第一种方法,自己动手,从零开始创建字节码,理论上可行,实际上很难。

    第二种方法,使用已有的一些能操作字节码的库,帮助我们创建class。

    目前,能够操作字节码的开源库主要有CGLibJavassist两种,它们都提供了比较高级的API来操作字节码,最后输出为class文件。

    比如CGLib,典型的用法如下:

    Enhancer e = new Enhancer();
    e.setSuperclass(...);
    e.setStrategy(new DefaultGeneratorStrategy() {
        protected ClassGenerator transform(ClassGenerator cg) {
            return new TransformingGenerator(cg,
                new AddPropertyTransformer(new String[]{ "foo" },
                        new Class[] { Integer.TYPE }));
        }});
    Object obj = e.create();
    

    比自己生成class要简单,但是,要学会它的API还是得花大量的时间,并且,上面的代码很难看懂对不对?

    有木有更简单的方法?

    有!

    换一个思路,如果我们能创建UserProxy.java这个源文件,再调用Java编译器,直接把源码编译成class,再加载进虚拟机,任务完成!

    毕竟,创建一个字符串格式的源码是很简单的事情,就是拼字符串嘛,高级点的做法可以用一个模版引擎。

    如何编译?

    Java的编译器是javac,但是,在很早很早的时候,Java的编译器就已经用纯Java重写了,自己能编译自己,行业黑话叫“自举”。从Java 1.6开始,编译器接口正式放到JDK的公开API中,于是,我们不需要创建新的进程来调用javac,而是直接使用编译器API来编译源码。

    使用起来也很简单:

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    int compilationResult = compiler.run(null, null, null, '/path/to/Test.java');
    

    这么写编译是没啥问题,问题是我们在内存中创建了Java代码后,必须先写到文件,再编译,最后还要手动读取class文件内容并用一个ClassLoader加载。

    有木有更简单的方法?

    有!

    其实Java编译器根本不关心源码的内容是从哪来的,你给它一个String当作源码,它就可以输出byte[]作为class的内容。

    所以,我们需要参考Java Compiler API的文档,让Compiler直接在内存中完成编译,输出的class内容就是byte[]

    代码改造如下:

    Map<String, byte[]> results;
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    StandardJavaFileManager stdManager = compiler.getStandardFileManager(null, null, null);
    try (MemoryJavaFileManager manager = new MemoryJavaFileManager(stdManager)) {
        JavaFileObject javaFileObject = manager.makeStringSource(fileName, source);
        CompilationTask task = compiler.getTask(null, manager, null, null, null, Arrays.asList(javaFileObject));
        if (task.call()) {
            results = manager.getClassBytes();
        }
    }
    

    上述代码的几个关键在于:

    1. MemoryJavaFileManager替换JDK默认的StandardJavaFileManager,以便在编译器请求源码内容时,不是从文件读取,而是直接返回String
    2. MemoryOutputJavaFileObject替换JDK默认的SimpleJavaFileObject,以便在接收到编译器生成的byte[]内容时,不写入class文件,而是直接保存在内存中。

    最后,编译的结果放在Map<String, byte[]>中,Key是类名,对应的byte[]是class的二进制内容。

    为什么编译后不是一个byte[]呢?

    因为一个.java的源文件编译后可能有多个.class文件!只要包含了静态类、匿名类等,编译出的class肯定多于一个。

    如何加载编译后的class呢?

    加载class相对而言就容易多了,我们只需要创建一个ClassLoader,覆写findClass()方法:

    class MemoryClassLoader extends URLClassLoader {
    
        Map<String, byte[]> classBytes = new HashMap<String, byte[]>();
    
        public MemoryClassLoader(Map<String, byte[]> classBytes) {
            super(new URL[0], MemoryClassLoader.class.getClassLoader());
            this.classBytes.putAll(classBytes);
        }
    
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            byte[] buf = classBytes.get(name);
            if (buf == null) {
                return super.findClass(name);
            }
            classBytes.remove(name);
            return defineClass(name, buf, 0, buf.length);
        }
    }
    

    除了写ORM用之外,还能干什么?

    可以用它来做一个Java脚本引擎。实际上本文的代码主要就是参考了Scripting项目的源码。

    完整的源码呢?

    在这里:https://github.com/michaelliao/compiler,连Maven的包都给你准备好了!

    也就200行代码吧!动态创建class不是梦!

    展开全文
  • javassist动态生成class

    千次阅读 2017-06-20 19:35:02
    什么是javassist? Javassist是一个开源的分析、编辑和创建Java字节码的...应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架。 关于java字节码的处理,目前有很多工具,如bcel,asm。不过这
      
    

    什么是javassist?

    Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架。

    关于java字节码的处理,目前有很多工具,如bcel,asm。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用javassist。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类
     

    联想

     由上可知,javassist 可以用来动态生成class文件,并且JVM可以直接加载生成的class文件。

    具体作用:

    设计一个对接系统,通过动态模型的增删改触发业务系统相应服务的调用。模型增删改方法动态发布为WebService服务。WebService服务采用CXF发布,动态类生成采用Javassist。由于WebService服务类需要添加WebService相关注解。

    实战演练

    从0开始实战,首先我们认识最初级的由javassist生成class类并且修改保存
    package com.bsoft.javassis;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.lang.reflect.Method;
    
    
    import javassist.CannotCompileException;
    import javassist.ClassPool;
    import javassist.CtClass;
    import javassist.CtConstructor;
    import javassist.CtField;
    import javassist.CtMethod;
    import javassist.CtNewMethod;
    import javassist.NotFoundException;
    
    public class TestJavassis {
    
    	/**
    	 * @param args
    	 * @author yuzg
    	 * update time 2017-06-20
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		/**
    		 * ClassPool是缓存CtClass对象的容器,所有的CtClass对象都在ClassPool中。
    		 * 所以,CtClass对象很多时,ClassPool会消耗很大的内存,为了避免内存的消耗
    		 * ,创建ClassPool对象时可以使用单例模式,
    		 * 或者对于CtClass对象,调用detach方法将其从ClassPool中移除
    		 * 在ClassPool源码中getDefault 是单例模式生成
    		 * 
    		 *  public static synchronized ClassPool getDefault() {
            if (defaultPool == null) {
                defaultPool = new ClassPool(null);
                defaultPool.appendSystemPath();
            }
    
            return defaultPool;
        }
    		 */
    		ClassPool classpool =ClassPool.getDefault();
    		//创建类名
    		CtClass ctClass = classpool.makeClass("com.bsoft.esb.IEsbInvoker1");
    //		ctClass.stopPruning(true);
    		try {
    			//添加属性
    	        ctClass.addField(CtField.make("private int age;", ctClass));
    	        //添加setAge方法
    	        ctClass.addMethod(CtMethod.make("public void setAge(int age){this.age = age;}", ctClass));
    	        ctClass.addMethod(CtMethod.make("public int getAge(){return this.age;}", ctClass));
    			byte[] byteArray = ctClass.toBytecode();
    	        FileOutputStream output = new FileOutputStream("D:\\IEsbInvoker1.class");
    	        output.write(byteArray);                                        
    	        output.close();
    	        
    			/***
    			 * 如果下面的判断和解冻方法不加会报错 
    			 * java.lang.RuntimeException: com.bsoft.esb.IEsbInvoker1 class is frozen
    			 * 原因解释如下:
    			 *  当CtClass对象通过writeFile()、toClass()、toBytecode()转化为Class后,
    			 *  Javassist冻结了CtClass对象,因此,JVM不允许再次加载Class文件,所以不允许对其修改。
    			 */
    	        if(ctClass.isFrozen()){
    				ctClass.defrost();
    			}
    			 ctClass = classpool.get("com.bsoft.esb.IEsbInvoker1");
    			System.out.println(ctClass);
    			CtField param = new CtField(classpool.get("java.lang.String"), "name", ctClass);  
    			 ctClass.addField(CtField.make("private java.lang.String sex;", ctClass));
    		     ctClass.addField(CtField.make("private java.lang.String name;", ctClass));
    		     ctClass.addMethod(CtNewMethod.setter("setName", param));  
    		     ctClass.addMethod(CtNewMethod.getter("getName", param));  
    //		     // 添加无参的构造体  
    //	        CtConstructor cons = new CtConstructor(new CtClass[] {}, ctClass);  
    //	        cons.setBody("{name = \"Brant\";}");  
    //	        ctClass.addConstructor(cons);  
    	     // 添加有参的构造体  
    		    CtConstructor   cons = new CtConstructor(new CtClass[] {classpool.get("java.lang.String")}, ctClass);  
    	        cons.setBody("{$0.name = $1;}");  
    	        ctClass.addConstructor(cons);  
    		    byteArray = ctClass.toBytecode();
    	        output = new FileOutputStream("D:\\IEsbInvoker1.class");
    	        output.write(byteArray);
    	        output.close();
    
    	        //ctClass转class后创建对象
    	        Object o =ctClass.toClass().newInstance();
    	        //这样写会报错:java.lang.ClassNotFoundException: com.bsoft.esb.IEsbInvoker1
    	        /***
    	         * 此时应该还在pool中
    	         */
    //	        Class.forName("com.bsoft.esb.IEsbInvoker1").newInstance();
    	        //获取方法
    	        Method methodSet = o.getClass().getMethod("setName", new Class[] {String.class});
    	       //反射原理
    	        methodSet.invoke(o, "Alen");
    	        
    	        Method getter = o.getClass().getMethod("getName");
    	        System.out.println("name:"+getter.invoke(o, null));
    		} catch (NotFoundException e) {
    			System.out.println(e.getMessage());
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}catch (CannotCompileException e) {
    			System.out.println(e.getMessage());
    			e.printStackTrace();
    		}
    		catch (IOException e) {
    			e.printStackTrace();
    		}catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    
    

    $0, $1, $2, ...  代表的含义:

     $ 0代表的是 this,$ 1代表方法参数的第一个参数、$ 2代表方法参数的第二个参数,以此类推,$N代表是方法参数的第N个。例如:  
    setName(String Name){
       $0.name=$1;
    }
    相当于 this.name=Name;




    分别查看两次保存文件前后的class 文件 可用debug断点
    首次保存生成的class文件:
    package com.bsoft.esb;
    
    public class IEsbInvoker1
    {
      private int age;
    
      public void setAge(int paramInt)
      {
        this.age = paramInt;
      }
    
      public int getAge()
      {
        return this.age;
      }
    }

    修改后:






    输出:
    name:Alen
    一个class 文件就生成好了。并且通过java反射机制可以明显看出,和jvm主动调用class类中的方法并无两样。稍后上传jar包资源文件

    javassist.jar下载路径: 点击下载javassist

    展开全文
  • 在阅读框架代码的时候,我们经常碰到自动生成class类,例如jdk中动态代理类、cglib代理类、spring AOP代理以及method.invoke()方法中自动生成的类GeneratedMethodAccessor1、以及lambda表达式等等。其中jdk、cglib...

    在阅读框架代码的时候,我们经常碰到自动生成的class类,例如jdk中动态代理类、cglib代理类、spring AOP代理以及method.invoke()方法中自动生成的类GeneratedMethodAccessor1、以及lambda表达式等等。其中jdk、cglib以及lamb解析中都会提供一个系统配置,在生成代理类的时候,会将类的字节码写入到项目文件夹的文件中。例如:

    jdk中生成动态代理时,设置系统配置  -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true。程序运行中使用到jdk的动态代理时,就会在项目文件夹下生成一份代理类的class文件。

    通过配置项自动生成动态类的class文件,对于只研究jdk动态代理的人来说足够使用了。但是,当我们想要了解更多的其他动态类的生成方法时,却有很多限制。例如,很多动态class类不会提供自动生成class文件的方法,还有就是查找配置项略显麻烦。

    下面提供一种通用的查看动态class信息的方法:

    1.在程序中,在动态类生成之后的任意一处设置一个断点:

    2. 新建一个文件夹,在文件夹中新建一个hsdb.bat文件,用记事本打开bat文件,写入以下内容:

    java -classpath "C:\Program Files\Java\jdk1.8.0_172\lib\sa-jdi.jar" sun.jvm.hotspot.HSDB

    将C:\Program Files\Java\jdk1.8.0_172改成你的%JAVA_HOME%地址。

    3.双击执行hsdb.bat,出现如下界面:

    4.点击file->Attach to HotSpot process,然后通过在控制台通过"jps -l"命令查询进程id,确定需要连接的程序:

    这一步中有可能出现因jre中缺失sawindbg.dll而导致异常,解决办法就是从jdk目录下查找该dll文件,然后拷贝到jre\bin目录下,重新连接虚拟机就可以了。

    5.点击Tools->class Browser,查看当前进程的所有类:

    6.点击选中需要查看的动态类,然后点击下面的create .class file,动态类就生成了:

     

     

    7.接着,在浏览器中打开网址:http://javare.cn/,对生成的class文件在线反编译:

    8.最后反编译结果如下:

    文章的最后要感谢博客作者提供的方法:查看CGLib生成的class文件方法

    展开全文
  • 一种Java运行时动态生成class的方法

    千次阅读 2017-05-11 09:21:56
    Java运行时动态生成class的方法Java是一门静态语言,通常,我们需要的class在编译的时候就已经生成了,为什么有时候我们还想在运行时动态生成class呢?因为在有些时候,我们还真得在运行时为一个类动态创建子类。...

    Java运行时动态生成class的方法

    Java是一门静态语言,通常,我们需要的class在编译的时候就已经生成了,为什么有时候我们还想在运行时动态生成class呢?

    因为在有些时候,我们还真得在运行时为一个类动态创建子类。比如,编写一个ORM框架,如何得知一个简单的JavaBean是否被用户修改过呢?

    以User为例:

    public class User {
        private String id;
        private String name;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    其实UserProxy实现起来很简单,就是创建一个User的子类,覆写所有setXxx()方法,做个标记就可以了:

    public class UserProxy extends User {
        private boolean dirty;
    
        public boolean isDirty() {
            return this.dirty;
        }
    
        public void setDirty(boolean dirty) {
            this.dirty = dirty;
        }
    
        @Override
        public void setId(String id) {
            super.setId(id);
            setDirty(true);
        }
    
        @Override
        public void setName(String name) {
            super.setName(name);
            setDirty(true);
        }
    }
    

    但是这个UserProxy就必须在运行时动态创建出来了,因为编译时ORM框架根本不知道User类。

    现在问题来了,动态生成字节码,难度有多大?

    如果我们要自己直接输出二进制格式的字节码,在完成这个任务前,必须先认真阅读JVM规范第4章,详细了解class文件结构。估计读完规范后,两个月过去了。

    所以,第一种方法,自己动手,从零开始创建字节码,理论上可行,实际上很难。

    第二种方法,使用已有的一些能操作字节码的库,帮助我们创建class。

    目前,能够操作字节码的开源库主要有CGLib和Javassist两种,它们都提供了比较高级的API来操作字节码,最后输出为class文件。

    比如CGLib,典型的用法如下:

    Enhancer e = new Enhancer();
    e.setSuperclass(...);
    e.setStrategy(new DefaultGeneratorStrategy() {
        protected ClassGenerator transform(ClassGenerator cg) {
            return new TransformingGenerator(cg,
                new AddPropertyTransformer(new String[]{ "foo" },
                        new Class[] { Integer.TYPE }));
        }});
    Object obj = e.create();
    

    比自己生成class要简单,但是,要学会它的API还是得花大量的时间,并且,上面的代码很难看懂对不对?

    有木有更简单的方法?

    有!

    换一个思路,如果我们能创建UserProxy.java这个源文件,再调用Java编译器,直接把源码编译成class,再加载进虚拟机,任务完成!

    毕竟,创建一个字符串格式的源码是很简单的事情,就是拼字符串嘛,高级点的做法可以用一个模版引擎。

    如何编译?

    Java的编译器是javac,但是,在很早很早的时候,Java的编译器就已经用纯Java重写了,自己能编译自己,行业黑话叫“自举”。从Java 1.6开始,编译器接口正式放到JDK的公开API中,于是,我们不需要创建新的进程来调用javac,而是直接使用编译器API来编译源码。

    使用起来也很简单:

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    int compilationResult = compiler.run(null, null, null, '/path/to/Test.java');
    

    这么写编译是没啥问题,问题是我们在内存中创建了Java代码后,必须先写到文件,再编译,最后还要手动读取class文件内容并用一个ClassLoader加载。

    有木有更简单的方法?

    有!

    其实Java编译器根本不关心源码的内容是从哪来的,你给它一个String当作源码,它就可以输出byte[]作为class的内容。

    所以,我们需要参考Java Compiler API的文档,让Compiler直接在内存中完成编译,输出的class内容就是byte[]。

    代码改造如下:

    Map<String, byte[]> results;
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    StandardJavaFileManager stdManager = compiler.getStandardFileManager(null, null, null);
    try (MemoryJavaFileManager manager = new MemoryJavaFileManager(stdManager)) {
        JavaFileObject javaFileObject = manager.makeStringSource(fileName, source);
        CompilationTask task = compiler.getTask(null, manager, null, null, null, Arrays.asList(javaFileObject));
        if (task.call()) {
            results = manager.getClassBytes();
        }
    }
    

    上述代码的几个关键在于:

    1 , 用MemoryJavaFileManager替换JDK默认的StandardJavaFileManager,以便在编译器请求源码内容时,不是从文件读取,而是直接返回String;

    2, 用MemoryOutputJavaFileObject替换JDK默认的SimpleJavaFileObject,以便在接收到编译器生成的byte[]内容时,不写入class文件,而是直接保存在内存中。

    最后,编译的结果放在Map

    class MemoryClassLoader extends URLClassLoader {
    
        Map<String, byte[]> classBytes = new HashMap<String, byte[]>();
    
        public MemoryClassLoader(Map<String, byte[]> classBytes) {
            super(new URL[0], MemoryClassLoader.class.getClassLoader());
            this.classBytes.putAll(classBytes);
        }
    
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            byte[] buf = classBytes.get(name);
            if (buf == null) {
                return super.findClass(name);
            }
            classBytes.remove(name);
            return defineClass(name, buf, 0, buf.length);
        }
    }
    

    除了写ORM用之外,还能干什么?

    可以用它来做一个Java脚本引擎。实际上本文的代码主要就是参考了Scripting项目的源码。

    也就200行代码吧!动态创建class不是梦!

    完整的源码呢?

    在这里:https://github.com/itguang/compiler,连Maven的包都给你准备好了!

    展开全文
  • Class文件格式实战:使用ASM动态生成class文件

    万次阅读 多人点赞 2014-04-05 13:24:09
    众所周知, JVM在运行时, 加载并执行class文件, 这个class文件基本上都是由我们所写的java源文件通过javac编译而得到的。 但是, 我们有时候会遇到这种情况:在前期(编写程序时)不知道要写什么类, 只有到运行...
  • 1 JDK动态代理 1.1 创建代理过程: 定义接口 实现接口 定义代理类,继承InvocationHandler接口 1.2 具体代码 接口: public interface Person { void say(); } 实现类: public class ...
  • cglib被hibernate用来动态生成po的字节码。CGLIB的底层是java字节码操作框架ASM。 今天简单看下cglib的用法。cglib的Enhancer说起来神奇,用起来一页纸不到就讲完了。它的原理就是用Enhancer生成一个原有类的子类,...
  • 根据xml文件生成C# 属性class类,附件含源码。分享给需要的朋友
  • 从页面上文本写一个拦截器,然后上传这个拦截器的源码,生成对象并调用对象的方法。 我当时的反应就是很懵逼的 。。。这个操作也太骚了吧 年前写了个用groovy来执行,但是会出现一些问题,不能满足需求。 年后...
  • ASM操作字节码,动态生成Java类class文件,模拟Spring的AOP实现原理。
  • springboot动态发布接口 动态编译class

    千次阅读 2020-05-17 20:05:36
    1.通过velocity模板,生成Java模板 ...动态编译成class 3.通过class.forName("包类名字")加载字节码成为class对象 4.通过获取spring的ApplicationContext手动把mapping注册到RequestMappingHandlerMapping...
  • java动态创建class-两种方式(写入文件和非文件)

    万次阅读 热门讨论 2018-09-07 16:52:54
    首先是写入文件方式: ...Test.java在org.myself.pojo包下,生成class文件在target/class下(重点:1.编译class 2.加载class文件) private static void createStudentByFile() throws Exception{ String st...
  • scss动态生成类名、样式值

    千次阅读 2020-10-22 12:52:19
    常常会有需求 根据不同的状态给元素设置不同的颜色值,类似状态标签等等 如图的标签 用scss的同学,可以用@each指令 完成一系列样式的设置 代码如下: $colors: ( blue: #008fff, grey: #909299, ...
  • vue动态添加class的几种方式

    千次阅读 2019-08-22 02:12:23
    备注: 本文整理了vue动态添加class的几种方式 状态:已完成、待整合2019-08-22 p1,p为类名 【对象】 对象的形式: 用花括号包裹起来,类名用引号, 第一个参数 类名, 第二个参数:boolean值 优点: 以对象的形式...
  • js 关于动态添加class样式的学习

    万次阅读 2018-05-04 18:27:45
    但是动态的添加class需要注意一下写法,因为class是js的保留字,不能直接使用,要通过className来动态的添加class class ==> className oP.class = 'red'; -- 错 oP.className = 'red'; --对 下边将刚刚用js实现的...
  • CGLib 动态生成 类及实例

    千次阅读 2016-12-29 15:06:11
    前两天拜读深入Java虚拟机时, 看到书里有提及可以用CGLib动态生成类及类实例的做法, 就将CGLib下载下来一试. 众所周知, Java在运行时加载Class字节码到虚拟机中运行. 如下示例代码: try { URL url = new URL...
  • 最近像研究下spring 原理,看到代理这块,想去看看JDK动态代理产生的过程,这里想要知道最终生成代理类的结构,于是需要知道class 文件的结构。 解决办法: 产生jdk 代理文件的方法 方法一:在调用测试代理的方法前...
  • 整体的效果:一、首先百度搜索layui的地址,然后下载layui的压缩包,,将压缩包的文件解压缩,...三、将整个页面分为三部分body标签中要引用的classclass="layui-layout-body" 3.1、头部部分:用一个大...
  • Java 动态生成类和实例, 并注入方法

    万次阅读 2016-12-29 16:29:01
    // 动态注入 @Override public Object invoke(Object obj, Method method, Object[] params) throws Throwable { Object ret = null; String name = method.getName(); if (name.equals("getRandomInt")) ...
  • 如果我们要研究JDK动态生成的代理类,此时则需要将内存中的代理类作为.class文件保存到磁盘,再通过Java反编译工具查看其源码;这个过程可以通过设置系统属性让JRE来自动完成或者通过IO流写入到磁盘
  • Java 神器byte buddy动态生成

    千次阅读 2019-05-14 16:32:09
    还有一个名气更大的库mockito,其核心就是基于byte buddy实现的,可以动态生成mock类,非常方便。另外一个大的应用就是 java agent,其主要作用是在class 被加载之前对其拦截,插入自己的代码。 我的需求是在指定...
  • 启动时加: -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
  • 代理分两种技术,一种是jdk代理(机制就是反射,只对接口操作),一种就是字节码操作技术。...先看看jvm class技术: 字节码改写: (一)jdk 动态代理: 1.定义业务逻辑 public interface Service { //
  • 如何获取动态代理生成的.class文件

    千次阅读 2018-07-18 11:53:44
    该示范以mybatis中动态生成的代理类mapper做示范   1、运行HSDB工具 (1)、打开cmd窗口,运行命令:java -classpath "%JAVA_HOME%/lib/sa-jdi.jar" sun.jvm.hotspot.HSDB回车后会出现以下弹框 (2...
  • 使用javaassist在内存中动态生成

    千次阅读 2015-11-20 20:28:32
    //把生成class文件写入文件,也可以不写入  byte[] byteArr = ctClass.toBytecode();  FileOutputStream fos = new FileOutputStream(new File("D://Emp.class"));  fos.write(byteArr);  fos.close();...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,088,870
精华内容 835,548
关键字:

动态生成class