GraalVM
GraalVM允许您提前将程序编译为本地可执行文件。 与Java VM相比,生成的程序具有更快的启动时间和更低的运行时内存开销。 这对于通常是短暂的命令行实用程序尤其有用。
GraalVM对Java反射的支持有限,它需要提前了解反射访问的程序元素。
反射访问
 Picocli当前使用反射来发现用@Command注释的类和方法 ,以及用@Option和@Parameters以及其他picocli注释注释的field , 方法或方法参数 。 未来的picocli版本可能会包含注释处理器,以在编译时完成此工作,但就目前而言,它使用了反射。 
ReflectionConfigGenerator工具
 Picocli 3.7.0包含picocli-codegen模块 ,以及一个可生成GraalVM配置文件的工具。 
 ReflectionConfigGenerator生成带有程序元素的JSON字符串,该元素将在基于picocli的应用程序中进行反射访问,以便提前将该应用程序编译为GraalVM的本机可执行文件。 
 ReflectionConfigGenerator的输出旨在传递给本native-image GraalVM实用程序的-H:ReflectionConfigurationFiles=/path/to/reflectconfig选项。 这允许将基于picocli的应用程序编译为本机映像。 
用法示例
 我们将使用picocli.codegen.aot.graalvm.Example类是用于测试picocli-codegen模块为例。 首先,我们将使用ReflectionConfigGenerator工具生成一个reflect.json配置文件。 接下来,我们将Example类编译为一个本机应用程序,最后,我们将运行此应用程序,并查看本机应用程序与在Hotspot上运行之间的启动时间有何不同。 
生成配置文件
 运行ReflectionConfigGenerator工具,并指定@Command类的一个或多个完全合格的类名称。 输出将打印到System.out ,因此您将需要将其重定向到文件: 
java -cp \
picocli-3.7.0.jar:picocli-codegen-3.7.0-tests.jar:picocli-codegen-3.7.0.jar \
picocli.codegen.aot.graalvm.ReflectionConfigGenerator picocli.codegen.aot.graalvm.Example > reflect.json 生成的reflect.json文件如下所示: 
[{"name" : "picocli.codegen.aot.graalvm.Example","allDeclaredConstructors" : true,"allPublicConstructors" : true,"allDeclaredMethods" : true,"allPublicMethods" : true,"fields" : [{ "name" : "spec" },{ "name" : "unmatched" },{ "name" : "timeUnit" },{ "name" : "file" }],"methods" : [{ "name" : "setMinimum", "parameterTypes" : ["int"] },{ "name" : "setOtherFiles", "parameterTypes" : ["[Ljava.io.File;"] },{ "name" : "multiply", "parameterTypes" : ["int", "int"] }]},
...
]| 小费 | 如有必要,可以排除具有系统属性 picocli.codegen.excludes类,picocli.codegen.excludes接受以逗号分隔的标准类名正则表达式列表,这些列表不应包含在结果JSON字符串中。 | 
编译本机映像
这假定您已安装GraalVM,并且具有先决条件。 从站点 :
要构建程序的本机映像,请使用GraalVM发行版的
bin目录中的native-image实用程序。 要进行编译,native-image取决于本地工具链,因此请确保:您的系统上可以使用glibc-devel,zlib-devel(C库和zlib头文件)和gcc。
 除devel软件包外,我还需要静态软件包glibc-static和zlib-static 。 
我们使用以下命令编译示例类:
graalvm-ce-1.0.0-rc6/bin/native-image \-cp picocli-3.7.0.jar:picocli-codegen-3.7.0-tests.jar \-H:ReflectionConfigurationFiles=reflect.json -H:+ReportUnsupportedElementsAtRuntime \--static --no-server picocli.codegen.aot.graalvm.Example reflect.json位于当前目录中,我添加了-H:+ReportUnsupportedElementsAtRuntime以获取有用的错误消息,以防万一出现问题。 
| 小费 | native-image --expert-options显示未在native-image --help输出中显示的其他编译选项的列表。 | 
运行本机映像
 如果编译顺利,我们现在在当前目录中有一个本地可执行文件picocli.codegen.aot.graalvm.example : 
$ ls -alh picocli*
-rwxrwxr-x 1 remko remko 15M Oct  4 21:35 picocli.codegen.aot.graalvm.example 可执行文件的名称是从主类名称派生的。 如果jar是可执行的jar(在清单中指定了Main-Class),则可以运行native-image [options] -jar jarfile为jar文件构建映像。 
让我们首先使用Java运行该应用程序,并为其计时,以查看启动需要多长时间。
$ time java -cp  picocli-3.7.0.jar:picocli-codegen-3.7.0-tests.jar \picocli.codegen.aot.graalvm.Example --version
3.7.0real    0m0.492s
user    0m0.847s
sys     0m0.070s在Java Hotspot上,大约需要半秒钟才能运行。 现在,我们运行本机映像:
$ time ./picocli.codegen.aot.graalvm.example --version
3.7.0real    0m0.003s
user    0m0.000s
sys     0m0.004s现在启动时间已降至3毫秒!
所有命令行解析功能均可以正常工作,并具有类型转换,验证和ANSI颜色帮助功能。 当您想用Java编写命令行应用程序和服务并使它们即时运行时,这是令人振奋的消息。
结论
GraalVM是一项令人兴奋的新技术,它允许Java程序作为本机代码运行。 这样可以减少内存使用和启动时间,这对于诸如命令行实用程序之类的短期运行的程序尤其有用。
 picocli-codegen模块中包含的ReflectionConfigGenerator工具允许基于picocli的应用程序以极快的启动时间编译为本地可执行文件。 
如果您喜欢这些项目, 请在GitHub上加注 ☆ GraalVM和picocli !
翻译自: https://www.javacodegeeks.com/2018/11/picocli-graalvm-fast-command-apps.html