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.pswp.cn/news/457370.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457370.shtml
英文地址,請注明出處:http://en.pswp.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…