Transformando JARs em binário com GraalVM
Como usar a GraalVM Native Image para compilar JARs Kotlin em binários nativos, eliminando a dependência de JVM e melhorando drasticamente o tempo de execução.
Kotlinautas
Esse conteúdo é oferecido e distribuído pela comunidade Kotlinautas, uma comunidade brasileira que busca oferecer conteúdo gratuito sobre a linguagem Kotlin em um espaço plural.

O que é um binário?
Binário é um executável do sistema , pode ser rodado diretamente, porque é composto totalmente por linguagem de máquina.
As vantagens são a velocidade de execução, que costuma ser BEM rápida, e o fato de não precisar de nenhuma linguagem instalada pra rodar o programa. O próprio sistema cuida disso.
GraalVM
GraalVM é uma máquina virtual da Oracle para aumentar a velocidade de aplicações. Uma das funções da GraalVM é a Native Images, que é uma maneira de unir código de qualquer linguagem da JVM (Java, Kotlin, Clojure, etc.) em um único arquivo totalmente em código de máquina. Eliminando a necessidade de utilizar uma JVM para rodar um projeto.
Esse processo de transformar código JVM em binário deve ser usado só quando você for colocar em produção. É demorado e consome bastante processamento e memória , então em desenvolvimento, o fluxo normal da JVM é mais prático.
Instalação da GraalVM
Há alguns documentos oficiais de instalação da GraalVM para algumas plataformas, sendo:
Instalação da Native Image
A Native Image pode ser instalada usando a GraalVM Updater, que é uma ferramenta utilizada para instalar utilitários da GraalVM. Essa instalação pode ser feita com o comando:
gu install native-image
Hello World
Agora vamos criar um Hello World em Kotlin para gerar o JAR desse Hello World para transformar em binário com Native Image.
Isso pode ser feito com qualquer editor, não há necessidade de utilizar o IntelliJ, mas caso prefira, crie um projeto no IntelliJ para isso.
Arquivo main.kt:
fun main(){
println("Olá Mundo!")
}
Agora precisamos transformar esse arquivo em um JAR. Para isso, podemos usar o kotlinc, que é o compilador do Kotlin. Vá até a pasta onde o arquivo está e rode o comando abaixo:
kotlinc main.kt -include-runtime -d main.jar
Agora temos o nosso JAR no arquivo main.jar. Caso você queira executar esse JAR, isso pode ser feito com o comando java -jar main.kt, que terá Olá Mundo! como resultado:
Olá Mundo!
Agora precisamos transformar esse JAR em binário, podemos fazer isso com o comando native-image. Dessa maneira:
native-image --static -jar main.jar
Com isso o processamento irá começar. A GraalVM ao longo do processamento irá mostrar alguns dados sobre o processo:
$ native-image --static -jar main.jar
Build on Server(pid: 5484, port: 35163)
[main:5484] classlist: 441.34 ms
[main:5484] (cap): 1,017.18 ms
[main:5484] setup: 1,581.26 ms
[main:5484] (typeflow): 2,216.25 ms
[main:5484] (objects): 516.04 ms
[main:5484] (features): 86.21 ms
[main:5484] analysis: 2,876.19 ms
[main:5484] universe: 131.56 ms
[main:5484] (parse): 610.96 ms
[main:5484] (inline): 518.10 ms
[main:5484] (compile): 2,818.48 ms
[main:5484] compile: 4,187.55 ms
[main:5484] image: 354.83 ms
[main:5484] write: 164.75 ms
[main:5484] [total]: 9,769.44 ms
Após o término desse processamento teremos um binário main com todo o código atual. Esse binário terá cerca de 12MB de tamanho.
Para executar esse binário, no Windows podemos usar o comando main no diretório que esse binário está, e em Linux/MacOS podemos usar ./main.
Velocidade
Podemos comparar o tempo de execução do JAR e do binário, caso você esteja em sistemas Linux/MacOS existe o comando time para medir o tempo de execução de um comando, comparando os dois métodos teremos o resultado abaixo:
$ time java -jar main.jar
Olá Mundo!
java -jar main.jar 0,12s user 0,02s system 64% cpu 0,114 total
$ time ./main
Olá Mundo!
./main 0,00s user 0,00s system 74% cpu 0,002 total
Podemos ver que a principal diferença entre os dois é a diferença de tempo que cada um executou. Enquanto java -jar main.jar demorou 0.12 segundos para rodar, ./main levou 0 segundos para rodar, de maneira quase instantânea. Claro, para programas pequenos a diferença pequena, mas para programas maiores como uma aplicação web essa diferença irá ficar bem maior.
Finalização
Neste artigo você aprendeu como utilizar a GraalVM para gerar binários de projetos JVM especialmente Kotlin, e executar esse binário final.