ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

从GraalVM到Quarkus系列-B002篇-Quarkus中的字节码框架gizmo

2021-02-17 11:03:03  阅读:485  来源: 互联网

标签:B002 tryBlock name 生成 Quarkus GraalVM class gizmo


从GraalVM到Quarkus系列

A000篇-忽悠你用GraalVM
A001篇-NativeImage相关的注解
B001篇-NativeImage相关的注解@TargetClass
A002篇-GraalVM中的动态代理
A003篇-NativeImage中的资源


从GraalVM到Quarkus系列-B002篇-Quarkus中的字节码框架gizmo


前言

Quarkus中很多功能用到字节码生成,由于NativeImage是不支持运行时动态生成字节码的,所以Quarkus将很多运行时动态生成的代码放在静态分析之前生成


一、是什么?

Quarkus中使用的字节码生成工具是gizmo框架,这是对asm框架的封装,使其食用口感更佳

二、使用步骤

1.引入包

pom.xml:

在这里插入图片描述

2.创建一个ClassCreator

代码:

var creator = new ClassCreator((name, data) -> {
    var path = Thread.currentThread().getContextClassLoader()
    	.getResource("").getPath();
    System.out.println("输出路径:" + path);
    //文件输出流输出生成的class文件
    try (OutputStream os = Files.newOutputStream(Path.of(path + "/" + name + ".class"))) {
        //class文件输出到maven的target/classes
        os.write(data);
    } catch (IOException e) {
        e.printStackTrace();
    }
}, "cbs/demo/MyClass", null, Object.class.getName())
  • ClassCreator方法的完整参数列表:(ClassOutput classOutput, String name, String signature, String superClass, String... interfaces)
  • ClassOutput是输出字节码用的,name是完整类名,signature是类型签名,superClass当然就是父类了,interfaces也就是接口列表了
  • 这个name.分割和/分割效果是一样的,ClassCreator构造函数里把.replace成/

3.创建一个MethodCreator

在这里插入图片描述

  • 顾名思义这个类肯定是创建方法用的
  • 方法内容是最简单的标准输出hello world
  • 而且没有返回值
  • 方法签名第二个参数也暗示了返回值是void
  • invokeVirtualMethod表示我们调用的是个虚方法
  • 第一个参数是要调用的方法签名,我们用ofMethod方法来生成,这个方法是静态导入的import static io.quarkus.gizmo.MethodDescriptor.ofMethod;
  • ofMethod的方法是这样定义的(所在的类,方法名,返回值类型,参数列表的类型):
    public static MethodDescriptor ofMethod(Class<?> declaringClass, String name, Class<?> returnType, Class<?>... parameterTypes)	
    
  • 因为System.out.println("字符串")使用了System的静态字段out,所以要先readStaticField读取这个静态字段
  • FieldDescriptor.of就是生成这个字段描述的方法
  • invokeVirtualMethod第二个参数就是调用的这个方法所在的实例,在这就是out
  • 最后invokeVirtualMethod的第三个参数是调用的方法参数列表,就把"hello gizmo啊"load进来即可

4.运行代码生成class文件

在这里插入图片描述

  • 用idea自带的class反编译打开
  • 可见我们代码生成的class已经在target/classes下了
  • 而且注释中还标明这个类是合成类

5.其他操作

  • 如果想在类上加注解,可以在类生成后:creator.addAnnotation(DemoAnnotation.class);
  • 这样生成的类就会标注@DemoAnnotation
  • try catch:
    var tryBlock = methodCreator.tryBlock();
    tryBlock.invokeVirtualMethod(
            ofMethod(PrintStream.class, "println", void.class, String.class),
            tryBlock.readStaticField(FieldDescriptor.of(System.class, "out", PrintStream.class)),
            tryBlock.load("我在try块中"));
    tryBlock.addCatch(IllegalStateException.class);
    tryBlock.close();
    
  • 生成的效果:
    在这里插入图片描述
  • 我在这只简单介绍这个框架的使用,实际可以进行的操作还是比较多的
  • gizmo自带的test就是很好的学习示例,感兴趣可以看下
    在这里插入图片描述

总结

  • 最近过年光顾着长肉了
  • 稍有懈怠,产量有点低…
  • 代码在此

标签:B002,tryBlock,name,生成,Quarkus,GraalVM,class,gizmo
来源: https://blog.csdn.net/cbs727505670/article/details/113831297

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有