kotlin编译失败_Kotlin使用GraalVM开发原生命令行应用

背景

之前用kotlin开发过一款根据建表DDL语句生成plantuml ER图的应用。被问如何使用,答曰"给你一个jar包,然后执行java -jar ddl2plantuml.jar ./ddl.sql ./er.puml 就可以了。是不是so easy?"

结果被吐槽了一番,

  1. 为什么不能像命令行应用一样提供相关帮助信息?
  2. 为什么是Java, 而不是一个原生命令行应用?

这个吐槽带来了一个思考: 为什么Java很少用于开发原生命令行(CLI)应用呢?我认为主要问题有2个

  1. Java通过JVM实现跨平台。也就是说,如果要使用Java应用需要先安装JRE。
  2. Java的优势在于JVM热点代码检测和运行时编译及优化,所以这是一门程序运行时间越长,速度越快的神奇语言。而付出的代价则是应用启动速度较慢。这与一次性启动运行的命令行应用的场景需求正相反。

方案

为了解决上述问题,引入2个名词

  1. Picocli
  2. GraalVM

Picocli

Picocli 致力于提供“最简便的方式来创建富命令行应用,这种应用可以在 JVM 上和 JVM 之外运行”

使用起来非常简单

fun main(args: Array) {    val cmd = CommandLine(Convert())    when {        args.isEmpty() -> {            cmd.usage(System.out)        }        else -> {            val exitCode = cmd.execute(*args)            exitProcess(exitCode)        }    }}@CommandLine.Command(name = "ddl2plantuml",        version = ["软件名称:Ddl2plantuml版本:V1.1.0"],        description = ["convert sql ddl to plantuml er"],        mixinStandardHelpOptions = true)class Convert : Callable {    @CommandLine.Parameters(index = "0", description = ["The sql ddl file that should be convert to plantuml er."])    lateinit var src: Path    @CommandLine.Option(names = ["-o", "--output"], description = ["The file where the plantuml file to be saved. default is console "])    private var target: Path? = null    override fun call(): Int {        require(src.toFile().exists()) { "ddl file must be existed!" }        when (target) {            null -> {                FileReader(src).read()                        .apply { ConsoleWriter(this).write() }            }            else -> {                FileReader(src).read()                        .apply { FileWriter(target!!, this).write() }            }        }        return 0    }}

效果

f6cb334f697f5de380e9881e396183ac.png

这里介绍用到的几个注解及概念

  • @Parameters 和 @Options 都是用来定义参数,区别在于 @Parameters根据位置区分,而@Options可以指定名称
aa31a154873f5e9805d4c7e45140ccb4.png
  • 退出码。call()方法返回的0表示退出码,用来描述命令行应用的执行结果。通常用0表示成功,其他数字为自定义异常。退出码不会影响程序的执行,但是有一个很实用的功能是当你通过连接的方式同时执行多个应用时,一个非零的退出码会中断这个组合。如: ./ddl2plantuml_mac ddl.sql |grep "table"
  • 版本及帮助信息。可以自定义并指定样式,version可以通过versionProvider自定义生成。

GraalVM

Go的一个宣传点是可以将程序编译为一个静态可执行文件,而Java也可以通过GraalVM做到这一点

GraalVM: Run Programs Faster Anywhere

这个slogan和Java的"Write Once, Run Anywhere"遥相呼应,同时又展示了极大的野心,准备带来下一个20年的辉煌。

GraalVM 是一个高性能的通用虚拟机,可以运行使用 JavaScript,Python 3,Ruby,R,基于 JVM 的语言以及基于 LLVM 的语言开发的应用。 GraalVM 消除了编程语言之间的隔离性,并且通过共享运行时增强了他们的互操作性。它可以独立运行,也可以运行在 OpenJDK,Node.js,Oracle,MySQL 等环境中。

可以看到GraalVM提供了非常强大的功能,这里我们不做展开介绍,只看如何解决我们遇到的问题。主要用到了2个功能特性

  1. 即时编译,提升程序启动速度
  2. Native Image,将应用编译为单个静态可执行文件

使用方式

  1. 安装GraalVM
  2. 安装 native-image 工具 gu install native-image
  3. 编译应用 native-image -jar target/ddl2plantuml-1.1.0.jar ddl2plantuml

编译后的native image不运行在Java VM上,但是包含了必要的组件,如内存管理和线程调度,这些组件来自另一个Substrate VM。这个过程称为提前编译

此时我们已经得到了一个可以直接执行的原生命令行应用

./ddl2plantuml_mac ddl.sql 

注意:

native image不支持Java的所有特性,尤其是对reflection的限制。在这次改造过程中,原来通过阿里的druid进行sql解析,但是druid使用了大量的reflection导致native image编译失败,所以改用jsqlparser。

其他

  1. Picocli提供了maven插件native-image-maven-plugin,用于编译阶段进行native image构建。但是建议分离开发和构建,在CICD中执行构建过程,可以节省开发时间,并构建不同平台的应用,解决开发环境局限
  2. 除了构建命令行应用,GraalVM也带来了更多的可能性,比如Java在FAAS中的应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457370.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Swift - 添加纯净的Alamofire

Swift - 添加纯净的Alamofire 如果你有代码洁癖,不能容忍任何多余的东西,请继续往下看. 1. 下载Alamofire (https://github.com/Alamofire/Alamofire) 2. 解压缩并打开 Alamofire.xcworkspace 3. 删除不必要的内容 (根据你的需求自己定) 4. 顺便把文件夹里面的无关内容也删除掉…

jquery 获取系统默认年份_你没有看错,爬网页数据,C# 也可以像 Jquery 那样

一:背景1. 讲故事前段时间搞了一个地方性民生资讯号,资讯嘛,都是我抄你的,你抄官媒的,小市民都喜欢奇闻异事,所以就存在一个需求,如何去定向抓取奇闻异事的地方号上的新闻,其实做起来…

linux下怎么编译运行C语言程序?

linux下的C语言编译器是gcc,C的编译器是g。 linux下编程可以使用编辑器vi或vim,建议使用vim,因为它有语法高亮显示。程序编写好后,假设你的程序名为test.c,可以使用gcc -o test test.c。test就是编译好的可执行程序./t…

undertow 怎么创建线程_为什么很多SpringBoot开发者放弃了Tomcat,选择了Undertow

点击上方“后端技术精选”,选择“置顶公众号”技术文章第一时间送达!作者:阿迈达toutiao.com/a6775476659416990212/前言在SpringBoot框架中,我们使用最多的是Tomcat,这是SpringBoot默认的容器技术,而且是内…

一起玩转CoordinatorLayout

作为Material Design风格的重要组件,CoordinatorLayout协调多种组件的联动,实现各种复杂的效果,在实际项目中扮演着越来越重要的角色。本篇博客将由浅到深,带你一起玩转CoordinatorLayout。 官方文档对CoordinatorLayout是这样描述的&#xf…

离散数学图论旅行规划问题_2020年MathorCup高校数学建模挑战赛——C 题 仓内拣货优化问题...

下面的链接是精华版思路,亮点是对第六问的探讨。高度概括一下:第一问曼哈顿,第二问用免疫,三问增加任务单,四问增加拣货员,五问改变复核台,六问亮点来探讨~ 有点皮MathorCup C题 仓内拣货优化问…

Asp.NetWebForm的控件属性

一:GridView: 1.绑定ID 的值:DataKeyNames"Id", 2.自动产生列的意思:AutoGenerateColumns 3.如何注册脚本:ClientScript.RegisterStartupScript(this.GetType(),"text","alert(删除成功)"&#xf…

【VBA编程】10.自定义集合

自定义集合类型,类似于变量声明,只是要将Dim关键字和New collection关键字搭配起来使用,其语法描述如下:其中集合名的命名方式同于标准变量的命名 Dim 集合名 As New collection 对于已经定义的集合对象,可以使用集合的…

git fork clone 区别_Working with Git | Git 与 GitHub

关于各位好,这里是 Chinas Prices Project 项目的知乎专栏。关于 CPP 项目,您可以在这篇文章里了解到更多的信息。若您对这个项目感兴趣,我们非常欢迎您与我们交流您的想法与见解。在一个团队的成员同时为一个项目进行开发工作时,…

舒适的路线(codevs 1001)

题目描述 DescriptionZ小镇是一个景色宜人的地方&#xff0c;吸引来自各地的观光客来此旅游观光。Z小镇附近共有N(1<N≤500)个景点&#xff08;编号为1,2,3,…,N&#xff09;&#xff0c;这些景点被M&#xff08;0<M≤5000&#xff09;条道路连接着&#xff0c;所有道路都…

PHP_Smarty

模板 数据与表现层的标签分离 smarty是PHP 与 HTML代码的分离 小型模板类 $smarty 的工作流程&#xff1a; 把需要显示的全局变量&#xff0c;赋值塞到对象内部的属性上&#xff0c;一个数组中.编译模板&#xff0c;把{$标签},解析成相应的<?php echo 代码引入编译后的PHP文…

读中文_挑战来了!康辉喊你读中文十级绕口令!

文章来源&#xff1a;央视频汉语桥木甬读桶不读涌&#xff0c;月农读脓不读胧。米更读粳不读梗&#xff0c;日青读晴不读睛。米宗读粽不读综&#xff0c;言丁读订不读钉。土竟读境不是镜&#xff0c;土平读坪不是评。耳令读聆不读岭&#xff0c;火登读灯不读澄。言甬读诵不读蛹…

ios 自定义键盘

由于项目需要&#xff0c;需要自定义键盘。ios系统键盘会缓存键盘输入&#xff0c;并保存在系统目录下的文件里&#xff0c;并且是明文存储&#xff0c;存在帐号密码泄漏风险。在别人代码基础上修改了下&#xff0c;美化了下界面&#xff0c;去掉了字符输入&#xff0c;加了点击…

对象入参指定泛型类型_为什么要使用泛型,而不是直接将类型作为参数传递?

其实很多类型系统都是用类型参数的的形式来实现Universal Type的&#xff0c;Parametric Polymorphism 和System F可以了解一下&#xff0c;如果只局限于一两个热门语言的话&#xff0c;可能会有此疑问&#xff0c;但是从type theory的角度来说&#xff0c;高阶类型本身就是typ…

【GOF23设计模式】迭代器模式

【GOF23设计模式】迭代器模式 来源&#xff1a;http://www.bjsxt.com/ 一、【GOF23设计模式】_迭代器模式、JDK内置迭代器、内部类迭代器 1 package com.test.iterator;2 /**3 * 自定义的迭代器接口4 */5 public interface MyIterator {6 void first(); //将游标指向第…

SQLServer 维护脚本分享(08)临时数据库(tempdb)

dbcc sqlperf(logspace) --各数据库日志大小及使用百分比dbcc loginfo --查看当前数据库的虚拟日志文件--临时表Tempdb最近使用情况 SELECT t1.session_id ,t1.internal_objects_alloc_page_count*8.0/1024 as internal_objects_alloc_MB ,t1.internal_objects_dealloc_p…

51单片机50个实例代码_【附代码】51单片机电子密码锁教程

简介大家好&#xff0c;这篇文章的内容是关于如何用51单片机来制作一个电子密码锁的教程&#xff0c;通过这篇教程可以让刚入门的朋友了解矩阵键盘、LCD1602的使用方法&#xff0c;以及密码输入和修改的程序介绍&#xff0c;我会对每个部分进行详细的介绍。首先我们来看一下这个…

旋转的正方体

<!DOCTYPE html><html lang"zh-cmn-Hans"><head><meta charset"utf-8" /><title>backface-visibility_CSS参考手册_web前端开发参考手册系列</title><meta name"author" content"Joy Du(飘零雾雨),…

8数据提供什么掩膜产品_博硕能为你提供什么产品?

自动喷漆设备应用于线条、木门、橱柜、楼梯、套房家具、办公家具、木饰面板、外墙保温装饰一体板板等产品领域&#xff0c;针对NC、PU、UV、水性漆和氟碳漆等不同种类的油漆&#xff0c;进行自动化喷涂和干燥作业。自动喷漆设备有多种规格型号&#xff0c;分为不同的喷涂方式。…

python3 实现对比conf 文件差异

用法&#xff1a; ./conf.py nginx1.conf nginx2.conf > diff.htmlconf.py#!/usr/bin/python import difflib import sys #### Usage: compare_nginx.conf.py filename1 filename2 >diff.html try:textfile1 sys.argv[1]textfile2 sys.argv[2] except Exception as…