「调用外部」【开发者成长】如果你只写CRUD,那这种技术栈你永远碰不到( 二 )


private static byte[] generate() {
ClassWriter classWriter = new ClassWriter(0); // 定义对象头;版本号、修饰符、全类名、签名、父类、实现的接口 classWriter.visit(Opcodes.V1_7, Opcodes.ACC_PUBLIC, ''org/itstack/demo/asm/AsmHelloWorld'', null, ''java/lang/Object'', null); // 添加方法;修饰符、方法名、描述符、签名、异常 MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, ''main'', ''([Ljava/lang/String;)V'', null, null); // 执行指令;获取静态属性 methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, ''java/lang/System'', ''out'', ''Ljava/io/PrintStream;''); // 加载常量 load constant methodVisitor.visitLdcInsn(''Hello World''); // 调用方法 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, ''java/io/PrintStream'', ''println'', ''(Ljava/lang/String;)V'', false); // 返回 methodVisitor.visitInsn(Opcodes.RETURN); // 设置操作数栈的深度和局部变量的大小 methodVisitor.visitMaxs(2, 1); // 方法结束 methodVisitor.visitEnd(); // 类完成 classWriter.visitEnd(); // 生成字节数组 return classWriter.toByteArray(); }
以上的代码,“小朋友,你是否有很多问好???^1024”,其实以上的代码都是来自于 ASM 框架的代码,这里面所有的操作与我们使用使用 javap -c XXX 所反解析出的字节码是一样的,只不过是反过来使用指令来编写代码。
1.定义一个类的生成 ClassWriter
2.设定版本、修饰符、全类名、签名、父类、实现的接口,其实也就是那句;public class HelloWorld
3.接下来开始创建方法,方法同样需要设定;修饰符、方法名、描述符等。这里面有几个固定标识;
 「调用外部」【开发者成长】如果你只写CRUD,那这种技术栈你永远碰不到
文章图片

4.执行指令;获取静态属性。主要是获得 System.out
5.加载常量 load constant,输出我们的HelloWorld methodVisitor.visitLdcInsn(''Hello World'');
6.最后是调用输出方法并设置空返回,同时在结尾要设置操作数栈的深度和局部变量的大小
这样输出一个 HelloWorld 是不还是蛮有意思的,虽然你可能觉得这编码起来实在太难了吧,也非常难理解。首先如果你看过我的专栏,用《Java写一个Jvm虚拟机》,那么你可能会感受到这里面的知识点还是不那么陌生的。另外这里的编写,ASM还提供了插件,可以方便的让你开发字节码。接下来就介绍一下使用方式。
五、有插件的帮助字节码开发也不是很难
对于新人来说如果用字节码增强开发一些东西确实挺难,尤其是一些复杂的代码块使用字节码指令操作还是很有难度的。那么,其实也是有简单办法就是使用 ASM 插件。这个插件可以很轻松的让你看到一段代码的指令码以及如何用ASM去开发。
1.安装插件(ASM Bytecode Outline)
 「调用外部」【开发者成长】如果你只写CRUD,那这种技术栈你永远碰不到
文章图片

2.测试使用
 「调用外部」【开发者成长】如果你只写CRUD,那这种技术栈你永远碰不到
文章图片

是不是看到有插件的帮助下,心里有所激动了,至少写这样的东西有了抓手。这样你就可以很方便的去操作一些增强字节码的功能了。
六、用字节码写出一个两数之和计算
好!有了上面的插件,也有了一些基础知识的了解。那么我们开发一个计算两数之和的方法,之后运行计算结果。
这是我们的目标
使用字节码编程方式实现