如何使用graalvm为带有反射功能的java代码生成native image
译自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格式的反射信息示例
- 确保您已安装 GraalVM JDK,下载地址如下:https://www.oracle.com/java/technologies/downloads/ 选择graalvm的版本即可
- 将以下源代码保存在名为 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 应用程序使用命令行参数来确定要执行的反射操作。
- 运行如下命令:
$JAVA_HOME/bin/javac ReflectionExample.java # 编译
$JAVA_HOME/bin/java ReflectionExample StringReverser reverse "hello" # 输出 olleh
$JAVA_HOME/bin/java ReflectionExample StringCapitalizer capitalize "hello" # 输出 HELLO
- 使用 native-image 命令创建本机可执行文件,如下所示:
$JAVA_HOME/bin/native-image --no-fallback ReflectionExample
- 使用以下命令运行生成的本机可执行文件:
./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格式的反射信息示例
以下步骤演示如何使用代理及其输出来创建依赖于反射且需要配置的本机可执行文件。
在工作目录中创建名为 META-INF/native-image 的目录:
mkdir -p META-INF/native-image
在启用代理的情况下运行应用程序生成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"] }]
}
]
构建本机可执行文件:
$JAVA_HOME/bin/native-image ReflectionExample
native-image 工具会自动使用 META-INF/native-image 目录中的配置文件。但是,建议将 META-INF/native-image 目录放到类路径上,可以通过 JAR 文件或使用标志 -cp 。(这样可以避免 IDE 用户在目录结构由 IDE 本身定义时出现混淆。)
测试可执行文件
./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 的引用。
更新配置以包含类 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"] }]
}
]重新生成本机可执行文件并运行,不会有报错了。
$JAVA_HOME/bin/native-image ReflectionExample
./reflectionexample StringCapitalizer capitalize "hello"
总结
graalvm让native镜像支持反射的关键是利用json提前告诉它哪些类的哪些方法会被反射调用,然后它就能力在运行时支持反射了。
如何使用graalvm为带有反射功能的java代码生成native image的更多相关文章
- ajax中网页传输(一)TEXT——带有删除功能的数据库表格显示练习
网页之间传输的三种方式:TEXT.JSON.XML. 本章将讲解带有TEXT形势的ajax网页传输 第一:body部分代码 <title>ajax中TEXT讲解并且带有删除功能的表格< ...
- 一种实现C++反射功能的想法(一)
Java的反射机制很酷, 只需知道类的名字就能够加载调用. 这个功能很实用, 想象一下, 用户只需指定类的名称, 就可以动态绑定类型, 而且只需通过字符串指定, 字符串的使用可以使得用户的修改只需修改 ...
- 使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法
使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法 效果展示 一个很简单的组件脚本 运行状态在Inspector面板可以随便修改字段和调用方法 方法调用日志 设计由来 最近在 ...
- 功能:Java注解的介绍和反射使用
功能:Java注解的介绍和反射使用 一.注解 1.注解介绍 java注解(Annotation),又称为java标注,是jdk5.0引入的一种机制. Java 语言中的类.方法.变量.参数和包等都可以 ...
- 进阶Java编程(10)反射与简单Java类
1,传统属性自动赋值弊端 简单Java类主要由属性构成,并且提供有setter与getter类,同时简单Java类最大的特征就是通过对象保存相应的类属性的内容.但是如果使用传统的简单Java类开发,那 ...
- java反射(四)--反射与简单java类
一.传统简单java类 简单的java类主要是由属性所组成,并且提供有相应的setter以及getter的处理方法,同时简单java类最大的特征就是通过对象保存相应的类的属性内容,但是如果使用传统的简 ...
- java jdbc ResultSet结果通过java反射赋值给java对象
在不整合框架的情况下,使用jdbc从数据库读取数据时都得一个个的get和set,不仅累代码还显得不简洁,所以利用java的反射机制写了一个工具类,这样用jdbc从数据库拿数据的时候就不用那么麻烦了. ...
- MyCP -tx -xt 功能的Java实现
MyCP -tx -xt 功能的Java实现 功能简介 java MyCP -tx XXX1.txt XXX2.bin 用来把文本文件(内容为十进制数字)转化为二进制文件 java MyCP -xt ...
- 软件工程作业 - 实现WC功能(java)
项目地址:https://github.com/yogurt1998/WordCount 要求 基本要求 -c 统计文件字符数(实现) -w 统计文件单词数(实现) -l 统计文件行数(实现) 扩展功 ...
- DrawerLayout带有侧滑功能的布局类(1)
DrawerLayout: DrawerLayout顾名思义就是一个管理布局的.使用方式可以与其它的布局类类似. DrawerLayout带有滑动的功能.只要按照drawerLayout的规定布局方式 ...
随机推荐
- [工程开发]当我们写一个tcp服务端的时候,我们在写什么?(一)
当我们写一个tcp服务器和客户端的时候,我们在写什么?(一) 本篇只聊服务端. 最近想搞一个服务器的协议,然后捏,简单搓个tcp服务器协议看看效果,主要是最近实在是没事干,闲得没事搓个服务器看看,当然 ...
- Vue第一篇 ES6的常用语法
01-变量的定义 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- Go ASM 学习笔记之 ppt 版
在 小白学标准库之反射 reflect 篇中介绍了接口和反射.然而,对于接口的类型转换,底层实现还是一知半解.在参考 Go 语言设计与实现 这本书接口章节时,又看不大懂.一个拦路虎摆在面前:汇编.不懂 ...
- solr-es
一.lucene 1.是什么 是apache提供的一套java写的用于全文检索工具包,该工具包提供了用于实现全文检索的api类,可用于实现搜索引擎功能. 2.搜索常用方法 顺序扫描法:应用于数据结构固 ...
- [转帖]使用MAT命令行工具生成堆dump分析文件
https://www.cnblogs.com/hellxz/p/use_mat_linux_command_line_generate_reports.html 写作目标 Java程序运行过程中,难 ...
- [转帖]shell编程:变量的数值计算实践(五)
https://www.cnblogs.com/luoahong/articles/9224495.html 算术运算符 变量的数值(整数)计算 1)(())用法:(此方法很常用)** 范例:sh ...
- 阿里云龙蜥8.6部署SQLSERVER2022的过程
阿里云龙蜥8.6部署SQLSERVER2022的过程 背景 之前总结过, 但是发现当时是preview版本. 这里想升级一下, 并且顺便抄一下他的部分说明 下载 wget https://packag ...
- [转帖]Grafana+influxdb+ntopng简易网络流量分析展示系统
Grafana逼格高,所以用它展示ntopng的数据 >_< 一,ntopng 根据官网资料 https://www.ntop.org/ntop/ntopng-influxdb-and-g ...
- [转帖]记一次sst文件损坏修复过程
https://tidb.net/blog/54e388c8 [2023-07-14 14:26:28]应用系统报警删除数据失败,查看日志报Region is unavailable,同时企业微信群也 ...
- [转帖]linux内存挂载
1.主要功能 在linux中,为了提高读写速度,可以将内存挂载到目录,常见的文件格式有tmpfs和ramfs. 2.挂载步骤 $ sudo mkdir /mnt/tmp $ sudo mkdir /m ...