译自Configure Native Image with the Tracing Agent graal官方文档 , 以下所有命令需要在linux环境下操作,graalvm也支持windows。

要为使用 Java 反射、动态代理对象、JNI 或类路径资源的 Java 应用程序构建本机可执行文件,应为 native-image 工具提供 JSON 格式的配置文件或在代码中预先计算元数据。

您可以手动创建配置文件,但更方便的方法是使用跟踪代理(即Tracing agent,下面用代理一词代称)生成配置。本指南演示如何使用代理进行配置 native-image 。当您在 JVM 上运行应用程序时,代理会自动为您生成配置。

若要了解如何使用代码中预先计算的元数据生成本机可执行文件,请参阅文档 - Reachability Metadata 可访问性元数据

本指南中的示例应用程序使用 Java 反射。该 native-image 工具仅部分检测使用 Java 反射 API 访问的应用程序元素。因此,您需要向它提供有关反射访问的类、方法和字段的详细信息。

不配置Json格式的反射信息示例

  1. 确保您已安装 GraalVM JDK,下载地址如下:https://www.oracle.com/java/technologies/downloads/ 选择graalvm的版本即可
  2. 将以下源代码保存在名为 ReflectionExample.java 的文件中:
     import java.lang.reflect.Method;
    
     class StringReverser {
    static String reverse(String input) {
    return new StringBuilder(input).reverse().toString();
    }
    } class StringCapitalizer {
    static String capitalize(String input) {
    return input.toUpperCase();
    }
    } public class ReflectionExample {
    public static void main(String[] args) throws ReflectiveOperationException {
    if (args.length == 0) {
    System.err.println("You must provide the name of a class, the name of its method and input for the method");
    return;
    }
    String className = args[0];
    String methodName = args[1];
    String input = args[2]; Class<?> clazz = Class.forName(className);
    Method method = clazz.getDeclaredMethod(methodName, String.class);
    Object result = method.invoke(null, input);
    System.out.println(result);
    }
    }

    该Java 应用程序使用命令行参数来确定要执行的反射操作。

  3. 运行如下命令:
    $JAVA_HOME/bin/javac ReflectionExample.java   # 编译
    $JAVA_HOME/bin/java ReflectionExample StringReverser reverse "hello" # 输出 olleh
    $JAVA_HOME/bin/java ReflectionExample StringCapitalizer capitalize "hello" # 输出 HELLO
  4. 使用 native-image 命令创建本机可执行文件,如下所示:
     $JAVA_HOME/bin/native-image --no-fallback ReflectionExample
  5. 使用以下命令运行生成的本机可执行文件:
    ./reflectionexample StringReverser reverse "hello"

    您将看到一个异常,类似于:

     Exception in thread "main" java.lang.ClassNotFoundException: StringReverser
    at java.lang.Class.forName(DynamicHub.java:1338)
    at java.lang.Class.forName(DynamicHub.java:1313)
    at ReflectionExample.main(ReflectionExample.java:25)

    这表明,根据静态分析,native-image 工具无法确定 StringReverser 类是否被使用,所以未将其包含在本机可执行文件中。

配置Json格式的反射信息示例

以下步骤演示如何使用代理及其输出来创建依赖于反射且需要配置的本机可执行文件。

  1. 在工作目录中创建名为 META-INF/native-image 的目录:

    mkdir -p META-INF/native-image
  2. 在启用代理的情况下运行应用程序生成json配置,如下所示:

    $JAVA_HOME/bin/java -agentlib:native-image-agent=config-output-dir=META-INF/native-image ReflectionExample StringReverser reverse "hello"

    此命令创建一个名为 reflect-config.json 的文件,其中包含类 StringReverser 的名称及其 reverse() 方法。

     [
    {
    "name":"StringReverser",
    "methods":[{"name":"reverse","parameterTypes":["java.lang.String"] }]
    }
    ]
  3. 构建本机可执行文件:

    $JAVA_HOME/bin/native-image ReflectionExample

    native-image 工具会自动使用 META-INF/native-image 目录中的配置文件。但是,建议将 META-INF/native-image 目录放到类路径上,可以通过 JAR 文件或使用标志 -cp 。(这样可以避免 IDE 用户在目录结构由 IDE 本身定义时出现混淆。)

  4. 测试可执行文件

    ./reflectionexample StringReverser reverse "hello" # 输出 olleh
    ./reflectionexample StringCapitalizer capitalize "hello"

    执行后会看到一个异常,类似于:

     Exception in thread "main" java.lang.ClassNotFoundException: StringCapitalizer
    at java.lang.Class.forName(DynamicHub.java:1338)
    at java.lang.Class.forName(DynamicHub.java:1313)
    at ReflectionExample.main(ReflectionExample.java:25)

    跟踪代理和 native-image 工具都无法确保配置文件完整。当您运行程序时,代理会观察并记录使用反射访问了哪些程序元素。在这种情况下,该 native-image 工具尚未配置为包含对类 StringCapitalizer 的引用。

  5. 更新配置以包含类 StringCapitalizer 。您可以使用以下 config-merge-dir 选项手动编辑 reflect-config.json 文件或重新运行跟踪代理以更新现有配置文件,如下所示:

     $JAVA_HOME/bin/java -agentlib:native-image-agent=config-merge-dir=META-INF/native-image ReflectionExample StringCapitalizer capitalize "hello"

    此命令更新 reflect-config.json 文件,以包含类 StringCapitalizer 的名称及其 capitalize() 方法。

     [
    {
    "name":"StringCapitalizer",
    "methods":[{"name":"capitalize","parameterTypes":["java.lang.String"] }]
    },
    {
    "name":"StringReverser",
    "methods":[{"name":"reverse","parameterTypes":["java.lang.String"] }]
    }
    ]
  6. 重新生成本机可执行文件并运行,不会有报错了。

     $JAVA_HOME/bin/native-image ReflectionExample
     ./reflectionexample StringCapitalizer capitalize "hello"

总结

graalvm让native镜像支持反射的关键是利用json提前告诉它哪些类的哪些方法会被反射调用,然后它就能力在运行时支持反射了。

如何使用graalvm为带有反射功能的java代码生成native image的更多相关文章

  1. ajax中网页传输(一)TEXT——带有删除功能的数据库表格显示练习

    网页之间传输的三种方式:TEXT.JSON.XML. 本章将讲解带有TEXT形势的ajax网页传输 第一:body部分代码 <title>ajax中TEXT讲解并且带有删除功能的表格< ...

  2. 一种实现C++反射功能的想法(一)

    Java的反射机制很酷, 只需知道类的名字就能够加载调用. 这个功能很实用, 想象一下, 用户只需指定类的名称, 就可以动态绑定类型, 而且只需通过字符串指定, 字符串的使用可以使得用户的修改只需修改 ...

  3. 使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法

    使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法 效果展示 一个很简单的组件脚本 运行状态在Inspector面板可以随便修改字段和调用方法 方法调用日志 设计由来 最近在 ...

  4. 功能:Java注解的介绍和反射使用

    功能:Java注解的介绍和反射使用 一.注解 1.注解介绍 java注解(Annotation),又称为java标注,是jdk5.0引入的一种机制. Java 语言中的类.方法.变量.参数和包等都可以 ...

  5. 进阶Java编程(10)反射与简单Java类

    1,传统属性自动赋值弊端 简单Java类主要由属性构成,并且提供有setter与getter类,同时简单Java类最大的特征就是通过对象保存相应的类属性的内容.但是如果使用传统的简单Java类开发,那 ...

  6. java反射(四)--反射与简单java类

    一.传统简单java类 简单的java类主要是由属性所组成,并且提供有相应的setter以及getter的处理方法,同时简单java类最大的特征就是通过对象保存相应的类的属性内容,但是如果使用传统的简 ...

  7. java jdbc ResultSet结果通过java反射赋值给java对象

    在不整合框架的情况下,使用jdbc从数据库读取数据时都得一个个的get和set,不仅累代码还显得不简洁,所以利用java的反射机制写了一个工具类,这样用jdbc从数据库拿数据的时候就不用那么麻烦了. ...

  8. MyCP -tx -xt 功能的Java实现

    MyCP -tx -xt 功能的Java实现 功能简介 java MyCP -tx XXX1.txt XXX2.bin 用来把文本文件(内容为十进制数字)转化为二进制文件 java MyCP -xt ...

  9. 软件工程作业 - 实现WC功能(java)

    项目地址:https://github.com/yogurt1998/WordCount 要求 基本要求 -c 统计文件字符数(实现) -w 统计文件单词数(实现) -l 统计文件行数(实现) 扩展功 ...

  10. DrawerLayout带有侧滑功能的布局类(1)

    DrawerLayout: DrawerLayout顾名思义就是一个管理布局的.使用方式可以与其它的布局类类似. DrawerLayout带有滑动的功能.只要按照drawerLayout的规定布局方式 ...

随机推荐

  1. 【TouchGFX】MIXINS - ClickListener

    ClickListener Click Listener混合器使它可以应用到其小部件,并能够通过使用回调扩展小部件来响应触摸输入. 在TouchGFX Designer中,可以通过在" Mi ...

  2. Redis-主从复制-哨兵模式

  3. 后端开发之光!Django应用的容器化部署实践~

    在此之前,我一直用uwsgi+virtualenv+nginx方式进行应用部署,操作起来比较麻烦,而且依赖于服务器上的Python版本,服务的管理方面单纯uwsgi + pid算不上特别麻烦但总没有d ...

  4. [转帖]Nginx 性能优化

    目录 1.调整 worker 进程数 2.调整 worker 连接数 3.调整 work 进程最大打开文件数 4.开启高效文件传输模式 5.限制文件上传大小 6.开启 gzip 压缩 7.本地缓存静态 ...

  5. Redis监控方法之二

    Redis监控方法之二 背景 前期整理过使用 exporter + prometheus 方式进行Redis监控的搭建过程 最近给同事研究clickhouse时发现 clickhouse 有对应的pl ...

  6. [转帖]CentOS8时间同步服务

    时间同步服务 CentOS7之前的版本用的是ntpdate服务,之后用的是chrony服务 默认是安装的了 查看版本 [root@centos8 ~]#rpm -qi chrony Name : ch ...

  7. 【转帖】nginx变量使用方法详解-5

    https://www.diewufeiyang.com/post/579.html 前面在 (二) 中我们已经了解到变量值容器的生命期是与请求绑定的,但是我当时有意避开了"请求" ...

  8. 【转帖】千亿参数大模型首次被撬开!Meta复刻GPT-3“背刺”OpenAI,完整模型权重及训练代码全公布

    https://cloud.tencent.com/developer/article/1991011 千亿级参数AI大模型,竟然真的能获取代码了?! 一觉醒来,AI圈发生了一件轰动的事情-- Met ...

  9. [转帖]模拟enq: TX - row lock contention争用

    https://www.modb.pro/db/623036 enq: TX - row lock contention它表示一个事务正在等待另一个事务释放被锁定的行.这种等待事件通常发生在并发访问数 ...

  10. [转帖]焱融全闪系列科普| 为什么 SSD 需要 NVMe?

    https://xie.infoq.cn/article/7026237b455c7d62f33afc4a9 NVMe 的由来 目前机械硬盘大多数使用 SATA (Serial ATA Advance ...