这样和妻子解释:Java动态代理机制详解(JDK和CGLIB
class文件简介及加载Java编译器编译好Java文件之后 , 产生.class 文件在磁盘中 。 这种class文件是二进制文件 , 内容是只有JVM虚拟机能够识别的机器码 。 JVM虚拟机读取字节码文件 , 取出二进制数据 , 加载到内存中 , 解析.class 文件内的信息 , 生成对应的 Class对象:
文章插图
class字节码文件是根据JVM虚拟机规范中规定的字节码组织规则生成的、具体class文件是怎样组织类信息的
下面通过一段代码演示手动加载 class文件字节码到系统内 , 转换成class对象 , 然后再实例化的过程:
a. 定义一个 Programmer类:
package samples;/*** 程序猿类* @author louluan*/public class Programmer {public void code(){System.out.println("I'm a Programmer,Just Coding.....");}}
b. 自定义一个类加载器:
package samples;/*** 自定义一个类加载器 , 用于将字节码转换为class对象* @author louluan*/public class MyClassLoader extends ClassLoader {public Class> defineMyClass( byte[] b, int off, int len){return super.defineClass(b, off, len);}}
c. 然后编译成Programmer.class文件 , 在程序中读取字节码 , 然后转换成相应的class对象 , 再实例化:
package samples;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.net.URL;public class MyTest {public static void main(String[] args) throws IOException {//读取本地的class文件内的字节码 , 转换成字节码数组File file = new File(".");InputStreaminput = new FileInputStream(file.getCanonicalPath()+"\\bin\\samples\\Programmer.class");byte[] result = new byte[1024];int count = input.read(result);// 使用自定义的类加载器将 byte字节码数组转换为对应的class对象MyClassLoader loader = new MyClassLoader();Class clazz = loader.defineMyClass( result, 0, count);//测试加载是否成功 , 打印class 对象的名称System.out.println(clazz.getCanonicalName());//实例化一个Programmer对象Object o= clazz.newInstance();try {//调用Programmer的code方法clazz.getMethod("code", null).invoke(o, null);} catch (IllegalArgumentException | InvocationTargetException| NoSuchMethodException | SecurityException e) {e.printStackTrace();}}}
以上代码演示了 , 通过字节码加载成class 对象的能力 , 下面看一下在代码中如何生成class文件的字节码 。
在运行期的代码中生成二进制字节码
【这样和妻子解释:Java动态代理机制详解(JDK和CGLIB】由于JVM通过字节码的二进制信息加载类的 , 那么 , 如果我们在运行期系统中 , 遵循Java编译系统组织.class文件的格式和结构 , 生成相应的二进制数据 , 然后再把这个二进制数据加载转换成对应的类 , 这样 , 就完成了在代码中 , 动态创建一个类的能力了 。
文章插图
在运行时期可以按照Java虚拟机规范对class文件的组织规则生成对应的二进制字节码 。 当前有很多开源框架可以完成这些功能 , 如ASM , Javassist 。
Java字节码生成开源框架介绍--ASM:
ASM 是一个 Java 字节码操控框架 。 它能够以二进制形式修改已有类或者动态生成类 。 ASM 可以直接产生二进制 class 文件 , 也可以在类被加载入 Java 虚拟机之前动态改变类行为 。 ASM 从类文件中读入信息后 , 能够改变类行为 , 分析类信息 , 甚至能够根据用户要求生成新类 。
不过ASM在创建class字节码的过程中 , 操纵的级别是底层JVM的汇编指令级别 , 这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解 。
下面通过ASM 生成下面类Programmer的class字节码:
package com.samples;import java.io.PrintStream;public class Programmer {public void code(){System.out.println("I'm a Programmer,Just Coding.....");}}
使用ASM框架提供了ClassWriter 接口 , 通过访问者模式进行动态创建class字节码 , 看下面的例子:
package samples;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import org.objectweb.asm.ClassWriter;import org.objectweb.asm.MethodVisitor;import org.objectweb.asm.Opcodes;public class MyGenerator {public static void main(String[] args) throws IOException {System.out.println();ClassWriter classWriter = new ClassWriter(0);// 通过visit方法确定类的头部信息classWriter.visit(Opcodes.V1_7,// java版本Opcodes.ACC_PUBLIC,// 类修饰符"Programmer", // 类的全限定名null, "java/lang/Object", null);//创建构造函数MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "
- 中国|浅谈5G移动通信技术的前世和今生
- 芯片|华米GTS2mini和红米手表哪个好 参数功能配置对比
- 桌面|日常使用的软件及网站分享 篇一:几个动态壁纸软件和静态壁纸网站:助你美化你的桌面
- 华为|台积电、高通、华为、小米接连宣布!美科技界炸锅:怎么会这样!
- 二维码|村网通?澳大利亚一州推出疫情追踪二维码 还考虑采用人脸识别和地理定位
- 不到|苹果赚了多少?iPhone12成本不到2500元,华为和小米的利润呢?
- 机器人|网络里面的假消息忽悠了非常多的小喷子和小机器人
- 华为|骁龙870和骁龙855区别都是7nm芯片吗 性能对比评测
- 花15.5亿元与中粮包装握手言和 加多宝离上市又进一步?|15楼财经 | 清远加多宝
- 究竟|免费的OPPO R1电视究竟怎么样