O Java 9 introduziu a ideia de imagens de tempo de execução modulares com o Project Jigsaw e resolveu oficialmente o problema de enviar o tempo de execução do Java como artefatos monolíticos. As imagens de tempo de execução monolíticas não eram apenas pesadas no uso de memória, mas também diminuíam o desempenho geral do aplicativo em execução. Agora podemos empacotar um subconjunto personalizado do JRE, com base nas necessidades individuais dos aplicativos executados nele e aumentar sua eficiência. Este artigo apresenta uma visão holística desse recurso de imagens de tempo de execução personalizadas introduzidas com o Java 9.
Uma visão geral
O impacto da ideia de criar uma imagem de tempo de execução modular com Java 9 é enorme. Ele abre as portas para um aplicativo personalizado construído diretamente da plataforma em que é executado. A plataforma Java vem aumentando sua funcionalidade a cada nova versão. Não é surpresa que em algum momento o tempo de execução será um artefato monolítico e terá um grande impacto na memória e no desempenho. Devido a isso, os desenvolvedores há muito solicitam uma saída para esse problema. Além disso, a maioria dos programas não usa a plataforma Java em sua totalidade. Se um programa pode ser otimizado para desempenho e uso de memória, por que a plataforma na qual ele é executado não pode ser personalizada também? Java 8 deu o passo inicial e tentou implementar algum aspecto dele com Perfis Compactos . O Java 9 avançou e implementou uma maneira de criar imagens de tempo de execução personalizadas sem restrições que Perfis compactos imposta. Foi necessária uma abordagem holística no empacotamento de imagens de tempo de execução. A própria plataforma é modularizada para habilitar esse recurso. O código do aplicativo empacotado em módulos pode ser enviado com imagens de tempo de execução personalizadas que contêm apenas os módulos de plataforma usados pelo aplicativo. Assim, um programa aplicativo pode ser um único artefato empacotado que inclui o JRE customizado. Isso certamente alavanca o desempenho, garantindo um tempo de inicialização com menos espaço de memória. Se o aplicativo for executado na nuvem, isso diminui consideravelmente a sobrecarga da rede e o tempo de download.
Perfil compacto
Embora o Java 9 tenha ultrapassado o conceito de Compact Profile introduzido com o Java 8, muitas vezes é útil entender e apreciar o marco alcançado. De certa forma, o Java 9 se alimentou da ideia e atualizou o conceito de um Perfil Compacto de forma mais holística.
Um Perfil compacto define subconjuntos da API da plataforma Java SE que podem reduzir o tamanho estático do Java Runtime. Essa ideia é basicamente direcionada para trabalhar em dispositivos com recursos limitados que possuem capacidades de armazenamento menores, como um dispositivo embarcado. Existem basicamente três perfis, chamados compact1 , compacto2 e compact3 . Cada perfil numerado superior é um superconjunto de seu perfil numerado rebaixado. Isso significa que compact1 é um subconjunto adequado de compact2 , compacto2 é um subconjunto adequado de compact3 e compact3 , por sua vez, é um subconjunto adequado da API Java 8 SE de pilha completa.
Referências:
- Perfis compactos, documentação do Java SE 8
- Visão geral de 8 perfis compactos do Java SE Embedded
- Uma introdução aos perfis compactos do Java 8
Apresentando JIMAGE
O JIMAGE é um formato de arquivo especial introduzido com o Java 9 para armazenar imagens de tempo de execução personalizadas. Este formato de arquivo é otimizado para desempenho e armazenamento. O formato do arquivo basicamente atua como um contêiner para recursos, classes e módulos do JDK e os indexa para pesquisa rápida e carregamento de classe mais rápido. Ao contrário de outros formatos de arquivo, como JARs e JMODs, o JIMAGE raramente é usado pelo desenvolvedor no que se refere aos componentes internos do JDK, exceto quando se deseja criar uma imagem de tempo de execução personalizada. O carregamento de classe é mais rápido com JIMAGE do que JARs ou JMODs, pois é especificamente otimizado para isso. Além disso, JIMAGE só pode ser usado em tempo de execução. JIMAGE ainda está em seus primeiros anos. Há muito pouca informação do desenvolvedor disponível; talvez mais serão expostos mais tarde.
Criando imagens personalizadas
Java 9 fornece o jlink ferramenta para criar imagens de tempo de execução específicas da plataforma. As imagens personalizadas contêm módulos específicos do aplicativo e os módulos necessários da plataforma. Como o tamanho da imagem de tempo de execução, também conhecido como JRE, é reduzido ao mínimo, a imagem do aplicativo junto com o JRE também é mínima. Ele agrupa o JRE como uma única unidade de entrega junto com o programa. O jlink ferramenta está localizada no /bin diretório do JDK9 diretório instalado. Existem várias opções disponíveis associadas a esta ferramenta que podem ser utilizadas de acordo com a necessidade. A descrição pode ser obtida usando o –ajuda opção disponível com o jlink comando. Aqui, ele é extraído por conveniência, ou você pode digitar jlink –help na linha de comando para obter a lista a seguir.
Uso:
jlink <options> --module-path <modulepath> --add-modules <module>[,<module>...]
Opção | Descrição |
–add-modules | Módulos raiz para resolver |
–bind-services | Link nos módulos do provedor de serviços e suas dependências |
-c, –compress=<0|1|2> –disable-plugin –endian | Ative a compactação de recursos: Nível 0:Sem compressão Nível 1:compartilhamento constante de strings Nível 2:CEP Desative o plug-in mencionado Ordem de bytes do jimage gerado (padrão:nativo) |
-h, –ajuda –ignore-assinatura-informações –launcher –limit-modules –lista de plug-ins | Imprima esta mensagem de ajuda Suprima um erro fatal quando JARs modulares assinados estiverem vinculados na imagem. Os arquivos relacionados à assinatura dos JARs modulares assinados não são copiados para a imagem de tempo de execução. Adicione um comando do iniciador com o nome fornecido para o módulo e a classe principal, se especificado. Limite o universo de módulos observáveis. Liste os plug-ins disponíveis. |
-p, –module-path –sem-arquivos de cabeçalho –não-páginas-man –saída –save-opts | Caminho do módulo Excluir arquivos de cabeçalho incluídos Excluir páginas de manual Localização do caminho de saída Salve as opções do jlink no arquivo fornecido |
-G, –strip-debug –suggest-providers [ | Tirar informações de depuração Sugira provedores que implementam os tipos de serviço fornecidos no caminho do módulo |
-v, –verboso -versão @ | Ativar rastreamento detalhado Versão informação Ler opções do arquivo |
Um exemplo simples
Aqui, vamos percorrer um programa muito simples do início ao fim de como criar uma imagem de tempo de execução de um aplicativo Java. Vamos supor que JDK9 está instalado corretamente e o PATH e JAVA_HOME variável de ambiente são definidas adequadamente. No meu caso, ele é instalado e configurado da seguinte forma (em uma plataforma Linux):
- JDK9 diretório instalado /usr/lib/jvm/java-9-oracle
- CAMINHO está definido como /usr/lib/jvm/java-9-oracle/bin
- JAVA_HOME está definido como /usr/lib/jvm/java-9-oracle
Etapa 1
Crie um diretório chamado /Home/SampleProject e um src diretório dentro dele (por exemplo, /Home/SampleProject/src ).
Etapa 2
Crie um diretório chamado org.app.test dentro do src diretório (como exemplo, /Home/SampleProject/src/org.app.test ).
Etapa 3
Agora, dentro do org.app.test diretório, crie um arquivo chamado module-info.java . E digite o seguinte conteúdo:
module org.app.test{ requires javafx.controls; exports org.app.test; }
Etapa 4
Agora, crie um diretório chamado org, app, test um dentro do outro (por exemplo, org.app.test/org/app/test ) e crie um arquivo chamado MyApplication.java dentro do teste diretório e digite o seguinte conteúdo:
package org.app.test; import javafx.application.Application; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.stage.Stage; public class MyApplication extends Application{ public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) throws Exception { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle("Congratulation!"); alert.setHeaderText("You did it. The application is running. Press OK to close"); alert.setContentText("You have successfully created a custom image"); alert.showAndWait().ifPresent(rs -> { if (rs == ButtonType.OK) { System.out.println("Pressed OK."); } }); } }
Etapa 5
Crie um /Home/SampleProject/mods diretório. Aqui, vamos salvar o código compilado. Compile o código-fonte da seguinte maneira. O diretório de trabalho atual é /Home/SampleProject .
javac -d mods --module-source-path src src/org.app.test/module-info.java src/org.app.test/org/app/test/MyApplication.java
Etapa 6
Agora, vamos criar o arquivo JAR e armazená-lo na lib diretório (como /Home/SampleProject/lib ) do seguinte modo:
jar --create --file lib/org.app.test.jar --main-class org.app.test.MyApplication -C mods/org.app.test .
Etapa 7
Para testar, execute o aplicativo da seguinte forma:
java --module-path lib -m org.app.test
Etapa 8
Agora, vamos criar o arquivo JMOD e salvá-lo no jmods diretório (por exemplo, Home/SampleProject/jmods ):
jmod create --class-path lib/org.app.test.jar jmods/org.app.test.jmod
Etapa 9
Por fim, vamos criar a imagem personalizada usando o seguinte comando:
jlink --module-path /usr/lib/jvm/java-9-oracle/jmods/:jmods --add-modules org.app.test --launcher runapp=org.app.test --output dist
Isso criará uma pasta chamada dist que contém tudo o que é necessário para executar o aplicativo. O programa, com o nome do iniciador dado como runapp , está contido em dist/bin diretório. Clique duas vezes nele para executar.
Figura 1: O programa está em execução
Isso é tudo.
Conclusão
Consulte a documentação apropriada para obter uma descrição detalhada de cada uma das opções de comando usadas neste artigo. Experimente um programa simples e construa-o do começo ao fim. Isso aumentaria a confiança necessária para experimentar um programa um pouco mais complicado, como usar mais de um módulo e lidar com suas dependências. O JDK9 capacitou os desenvolvedores a preparar sua bagagem de tempo de execução para ser preenchida apenas com os módulos necessários. Isso é incrível e excelente, algo que a maioria de nós esperava do Java há muito tempo. Um aplicativo Java agora pode se livrar da bagagem que tinha que carregar por aparentemente pouca razão e se tornar uma plataforma otimizada na distribuição.