[Pesquisar este blog]

quinta-feira, 11 de janeiro de 2018

POO::Fundamentos-02-Objetos, Tipos e Classes

POO-F-01-Características POO-F-03-Criação de Objetos

Compreendemos e interagimos com o mundo, em grande parte, através do conceito de objetos [6], que, conforme Jamsa & Klander [1], são simplesmente coisas ou entidades do mundo real.


Observando os objetos que existem ao seu redor, note que, provavelmente, todos são conhecidos. Mas as palavras que dão nome a cada um destes objetos são, de fato, nomes? A maioria dos termos que dão nome aos objetos conhecidos são substantivos e, diferentes dos nomes próprios, dados às pessoas, animais de estimação ou coisas especiais, os nomes dos objetos acabam designando algo maior: categorias de objetos. Habitualmente criamos categorias de objetos, usando o nome destas categorias para lidar com os muitos objetos que pertencem a cada categoria.

Tomemos um objeto conhecido, por exemplo, um livro. A simples menção do nome desta categoria de objeto nos leva, automaticamente, a imaginar algum livro e associar características destes objetos, como tamanho, espessura, título, conteúdo, autor e eventualmente outras que para nós estão ligadas a tal objeto. Também sabemos que existem muitos livros, que combinam, diferentemente as características possíveis destes objetos. Então, ao entrar numa livraria ou biblioteca, você não tem dificuldade de reconhecer os muitos livros distintos que lá existem, a despeito dos variados formatos, tamanhos, espessuras, capas e conteúdos variados [6][7].

Isto indica que somos capazes de reconhecer este tipo de objeto pelo conjunto de características comuns com as quais os descrevemos. A palavra livro serve, assim, para designar um imenso conjunto de objetos que compartilham um grupo de características comuns, ou seja, uma categoria de objetos, o mesmo que um tipo de objeto ou uma classe de objetos. Na POO, os termos classe e tipo são frequentemente considerados como sinônimos. 

Surgem aqui dois conceitos importantes da orientação a objetos:
  • classificação, que consiste na criação de categorias ou tipos de objetos que compartilham características e comportamento comuns;
  • encapsulamento, que estabelece um agrupamento de ideias correlacionadas e pode ser tratado como uma unidade por meio do seu nome.

No exemplo que analisamos, livro é uma classe de objetos que encapsula conceitos como formato, tamanho, espessura (ou número de páginas), título, autor e eventualmente outros.´

Os conceitos encapsulados em uma classe podem, então, representar características de seus objetos (como o tamanho de um livro), ou mesmo estados de seus objetos (como a situação ligado/desligado de uma máquina). Estas características e estados são conhecidas como atributos.

Além dos atributos, uma classe pode possui operações, ou seja, pode incluir comportamentos ou ações possíveis para os objetos da classe. Em geral, as operações atuam sobre os atributos e, assim, podem modificar as características ou estados dos objetos da classe.

Temos assim que os objetos encapsulam atributos (características e estados próprios) e também operações (comportamentos e ações possíveis), como ilustrado a seguir.


A sintaxe para declaração de uma classe utilizando a linguagem de programação Java é como segue:

<acesso> class <Nome> {
[declaração de atributos]
[declaração de métodos]
[declaração de construtores]
}

Entre os símbolos <> temos os elementos obrigatórios:
* acesso - especificador de acesso (que serão vistos na lição Encapsulamento);
* Nome - nome da classe, dado por meio de identificador válido.

Entre os símbolos [] temos os elementos opcionais:
* declaração de atributos - que definem o tipo e o nome dos atributos da classe;
* declaração de métodos - que definem as operações presentes na classe;
* declaração de construtores - que definem as operações especiais de criação de objetos.

Uma classe simples, em Java ou C#, pode ser declarada como:

class Livro {
}

As classes podem possuir, opcionalmente, um número variável de atributos, de métodos e de construtores. Os atributos e operações de uma classe serão discutidos nas próximas lições.

Finalizando, para que os objetos do mundo real possam existir, devem ser criados ou fabricados, possibilitando que sejam usados. Na POO a criação de objetos é também uma etapa importante, que seja tratada na próxima lição.

POO-F-01-Características POO-F-03-Criação de Objetos

Referências Bibliográficas

[1] JAMSA, K.; KLANDER, L.. Programando em C/C++: a bíblia. São Paulo: Makron Books, 1999.
[2] PAGE_JONES, M.. Fundamentos do Desenho Orientado a Objeto com UML. São Paulo: Makron Books, 2001.
[3] SOMMERVILLE, I.. Software Engineering. 6th. Ed. Harlow: Pearson, 2001.
[4] DEITEL, H.M.; DEITEL, P.J.. Java: como programar. 6a, Ed. Pearson Prentice-Hall: São Paulo, 2005.
[5] SAVITCH, W.. C++ Absoluto. Pearson Addison-Wesley: São Paulo 2004.
[6] JANDL JR., P.. Introdução ao C++. São Paulo: Futura, 2003.
[7] JANDL JR., P.. Java - guia do programador. São Paulo: Futura, 2003.
[8] RUMBAUGH, J.; BLAHA, M.; PREMERLANI, W.; EDDY, F.; LORENSEN, W.. Object-oriented modeling and design. Englewoods Cliffs: Prentice-Hall, 1991.

POO::Fundamentos-01-Características da POO

POO-F-00-Apresentação POO-F-02-Objetos, Tipos e Classes
A programação orientada a objetos, ou apenas POO, é a técnica dominante no desenvolvimento de software. Todo programador e todo projetista de software deve  dominar os conceitos da orientação a objetos (OO) e das técnicas fundamentais de sua programação.


Concebida há várias décadas, a OO deu origem a muitas linguagens de programação de sucesso, como Eiffel, Smalltalk, C++, Java e C#, entre dezenas de outras. As motivações para utilização desta técnica de projeto e de programação são sua capacidade de representação, que facilita o projeto, além de sua constituição modular, que podem aumentar a produtividade e reduzir os custos de desenvolvimento e de manutenção.

É possível afirmar que, no sentido mais simples, um objeto é uma coisa ou entidade do mundo real [1]. Já o termo orientado significa dirigido ou direcionado.

Assim, o termo orientado a objetos, conforme Page-Jones, é intrinsecamente destituído de qualquer sentido [2], pois como o termo objeto se aplica a, praticamente, qualquer coisa, resulta em algo como "direcionado a qualquer coisa". Por conta disso, sempre houve considerável dificuldade a respeito de uma definição concordante desta denominação.

Comumente, o projeto orientado à objetos é compreendido como uma estratégia onde os projetistas de sistemas pensam em termos de coisas ao invés de operações ou funções [3]. A construção de um sistema orientado a objetos (OO) é a combinação de vários objetos que interagem entre si.

Outros autores, como Deitel & Deitel [4], Savitch [5] e o Page-Jones [2] preferem definir a orientação a objetos como uma técnica de projeto que agrupa um conjunto de conceitos fundamentais: classificação, encapsulamento, especialização, generalização, identidade, ocultação de informações, polimorfismo, retenção de estado e troca de mensagens.

Estes conceitos podem ser rapidamente definidos como segue.

Classificação

Consiste na criação de categorias ou tipos de objetos que compartilham características e comportamento comuns. É uma ação natural no nosso modo de compreender o mundo a nossa volta [6]. A classificação ocorre por meio da criação de classes (tipos de objetos), que são modelos que permitem a geração de novos objetos, que terão as mesmas características e comportamentos do modelo que os originou [2]. Uma classe pode abrigar características (ou atributos) do tipo, assim como comportamentos (ou operações) sobre suas características.

Encapsulamento

É o agrupamento de ideias correlacionadas na forma unidades, módulos ou classes, de maneira que tal conceito pode usado apenas por meio de seu nome [2]. O encapsulamento também determina a representação do objeto, ou seja, possibilita que um objeto seja usado apenas por sua aparência exterior [6]. 

Especialização

Mecanismo da orientação a objetos pelo qual é possível a criação de novas classes (tipos) a partir de outras existentes, para adição de características e operações. A especialização é usualmente denominada de herança, onde uma classe B compartilha características e operações definidas em outra A [6], ou seja, a herança (de B a partir de A) é habilidade de B no uso de elementos A, como se estivessem definidos no próprio B [2]. A herança permite a criação de famílias de classes.

Generalização

Capacidade de utilizar objetos de tipos diferentes considerando apenas seus elementos comuns, ou seja, aqueles usualmente herdados de seus ancestrais comuns. Isto permite que objetos efetivamente diferentes possam ser usados para a realização de uma tarefa específica, o que confere grande flexibilidade aos sistemas assim construídos. Também pode se referir a construção de classes genéricas, ou seja, capazes de realizar suas operações sobre conteúdos internos diferentes [2][7].

Identidade

É a propriedade de cada objeto de ser unicamente distinguido dos demais [6], ou seja, sua identidade, permitindo seu tratamento individual [2]. É comum a existência de um identificar de objetos (object identifier - oid) nos sistemas de programação orientada a objetos.

Ocultação de informações

Permitindo preservar informações importantes dentro do objeto, externando apenas o que se julga conveniente ou necessário. Partes da própria construção do objeto (sua implementação) podem ser ocultadas pelo mesmo mecanismo. A ocultação das informações é obtida por meio dos mecanismos de encapsulamento [2][6][7].

Polimorfismo

Mecanismo essencial dos sistemas orientados a objeto que possibilita admitir muitas formas. Na orientação a objetos o polimorfismo pode se manifestar no acionamento de operações, na generalização e especialização.

Retenção de estado

Se refere a habilidade de um objeto de guardar informações sobre seu próprio estado [2], ou seja, é a memória própria de cada objeto que serve para armazenar suas características individuais e também outros dados que mantém consigo (seus estados), usualmente na forma de atributos [6].

Troca de mensagens

Uma mensagem é o veículo pelo qual um objeto remetente (caller) transmite um pedido a um objeto destinatário (receiver) para que ele realize uma de suas operações [2]. Os objetos de uma mesma classe, ou seja, do mesmo tipo, são capazes de receber os mesmos tipos de mensagens [4], pois podem realizar as mesmas operações.

Os objetos mantêm informações próprias que constituem seu estado local, além de prover operações para modificar, de maneira limitada, tal estado.

Assim, um objeto combina dados e operações específicas, o que define um conjunto particular de responsabilidades. Um sistema OO é um conjunto de objetos que se inter-relacionam para produzir os resultados desejados [7]

Assim, a programação orientada a objetos é uma forma particular de organizar o desenvolvimento de software como uma coleção de objetos que incorporam tanto uma estrutura de dados como comportamentos [8].

POO-F-00-Apresentação POO-F-02-Objetos, Tipos e Classes

Referências Bibliográficas

[1] JAMSA, K.; KLANDER, L.. Programando em C/C++: a bíblia. São Paulo: Makron Books, 1999.
[2] PAGE_JONES, M.. Fundamentos do Desenho Orientado a Objeto com UML. São Paulo: Makron Books, 2001.
[3] SOMMERVILLE, I.. Software Engineering. 6th. Ed. Harlow: Pearson, 2001.
[4] DEITEL, H.M.; DEITEL, P.J.. Java: como programar. 6a, Ed. São Paulo: Pearson Prentice-Hall, 2005.
[5] SAVITCH, W.. C++ Absoluto. São Paulo: Pearson Addison-Wesley, 2004.
[6] JANDL JR., P.. Introdução ao C++. São Paulo: Futura, 2003.
[7] JANDL JR. P.. Java - guia do programador. 3a. Ed. São Paulo: Novatec, 2015.
[8] RUMBAUGH, J.; BLAHA, M.; PREMERLANI, W.; EDDY, F.; LORENSEN, W.. Object-oriented modeling and design. Englewoods Cliffs: Prentice-Hall, 1991.

Curso de POO [_Índice_das_Lições_]

A programação orientada a objetos, ou apenas POO, é a técnica dominante no desenvolvimento de software. Como todo programador projeta software, consciente ou inconscientemente, é importante que tenha domínio pleno dos conceitos da orientação a objetos (OO) e das técnicas fundamentais de sua programação.

Para tratar todos os conceitos necessários, provendo alguns exemplos, o material foi dividido em partes, cada qual com seu conjunto próprio de lições, publicadas em posts separados.
Parte I -- POO Fundamental está completa. Como o material está tendo uma boa recepção, planejo produzir também a Parte II -- POO Plena.  Se tudo continuar assim, completo a série.

Finalmente, os exemplos utilizarão a linguagem de programação Java e também C#, para contemplar um conjunto maior de interesses.

segunda-feira, 8 de janeiro de 2018

Java 9::Jigsaw - a nova modularidade da plataforma (Parte III)

O Jigsaw trouxe um novo e interessante sistema de modularização para a versão 9 do Java, o qual soluciona muitos problemas das versões anteriores, além de proporcionar novas facilidades na construção de aplicações.
A parte III deste post traz um exemplo simples que mostra o essencial da construção de aplicações modularizadas, incluindo o uso do jlink. para a criação de imagens executáveis (runtime images), isto é, máquinas virtuais Java customizadas. A parte I abordou o conceito de modularidade e a especificação do novo artefato module trazida pelo Jigsaw; enquanto a parte II discute a implementação do Jigsaw na plataforma Java.
Ao longo deste post, use ';' como separador de diretório no Microsoft Windows e ':' no Unix/Linux. Note que %JAVA_HOME%/jmods é o diretório, no Windows que contém o módulo java.base.jmod (e os demais módulos padrão do JDK). Verifique sua instalação em caso de dúvidas.

Aplicação Simples (módulo único)

Uma aplicação simples é constituída por classes distribuídas em um pacote (ou mais) encapsulados em um único módulo. Além disso, estas classes não serão utilizadas por outras aplicações, ou seja, não serão exportadas para outros módulo, ou, em outros termos, observáveis por outros módulos.

Criaremos uma aplicação no estilo clássico do "Hello World" para começar.

1.
Crie um diretório Jigsaw em um lugar conveniente de seu sistema de arquivos. Entre neste diretório.
md Jigsaw
cd Jigsaw

2.
Crie um subdiretório para o código fonte (src), com subdiretórios para cada pacote e subpacote necessários, usando o seguinte esquema: src\<nome.pacote>\<subdir1>[\<subdir2>...].
Neste exemplo será necessário apenas um pacote (cujo nome longo é apenas ilustrativo).
md src\br.gov.sp.fatec.saudacoes\br\gov\sp\fatec\saudacoes

3.
Neste subdiretório crie o arquivo Main.java com o conteúdo que segue. Este é o código da aplicação simples que estamos construindo.
package br.gov.sp.fatec.saudacoes;

public class Main {
   public static void main(String[] args) {
      System.out.println("Olá Jigsaw!");
   }
}

4.
Navegue para o subdiretório que denomina o pacote (src\br.gov.sp.fatec.saudacoes):
cd ..\..\..\..\..

5.
Neste subdiretório crie o arquivo module-info.java, que é o descritor do módulo br.gov.sp.fatec.saudacoes, com o conteúdo que segue.
module br.gov.sp.fatec.saudacoes {
}

6.
Navegue para o diretório inicial (Jigsaw):
cd ..\..

7.
Crie um subdiretório para os módulos compilados (modules).
md modules\br.gov.sp.fatec.saudacoes


8.
Compile os arquivos de cada subpacote (apenas um neste exemplo).
(O comando abaixo foi separado em várias linhas para melhorar a legibilidade, mas deve ser fornecido em uma única linha!)
javac -d modules\br.gov.sp.fatec.saudacoes
      src\br.gov.sp.fatec.saudacoes\br\gov\sp\fatec\saudacoes\Main.java

A opção -d é seguida do diretório onde o código binário das classes deve ser armazenado, respeitando a estrutura de pacotes. O último argumento é o nome do arquivo que será compilado.

9.
Compile o arquivo de informação de cada módulo (apenas um neste exemplo).
(O comando abaixo foi separado em várias linhas para melhorar a legibilidade, mas deve ser fornecido em uma única linha!)
javac -d modules\br.gov.sp.fatec.saudacoes
      src\br.gov.sp.fatec.saudacoes\module-info.java

10.
É possível usar a JVM para listar os módulos disponíveis.
java --module-path modules --list-modules
A opção --module-path é seguida de uma lista de diretórios que contém os módulos não integrantes do JDK/JRE. A opção --list-modules determina a ação a ser tomada pela JVM.

11.
E também usar a JVM para obter informação de módulos observáveis.
(O comando abaixo deve ser fornecido em uma única linha!)
java --module-path modules
     --describe-module br.gov.sp.fatec.saudacoes

Aqui a opção --module-path é seguida de uma lista de diretórios que contém os módulos não integrantes do JDK/JRE. Já a opção --describe-module deve ser seguida do nome do módulo que deve ser descrito.
O resultado deve ser como segue:
br.gov.sp.fatec.saudacoes file:///C:/Users/Jandl/workspace/Jigsaw/modules/br.gov.sp.fatec.saudacoes/
requires java.base mandated
contains br.gov.sp.fatec.saudacoes

Observe que o módulo br.gov.sp.fatec.saudacoes requer (obrigatoriamente) o módulo java.base, apesar de seu descritor não explicitar tal necessidade.

12.
Para executar a aplicação simples, organizada como um módulo, usamos o comando que segue.
(O comando abaixo deve ser fornecido em uma única linha!)
java --module-path modules
     -m br.gov.sp.fatec.saudacoes/br.gov.sp.fatec.saudacoes.Main

A opção --module-path é seguida de uma lista de diretórios que contém os módulos não integrantes do JDK/JRE; enquando a opção -m deve ser seguida pelo nome do módulo e da classe que deve ser executada, mas sempre usando o separador '/'.
O resultado deve ser como segue:
Olá Jigsaw!
A listagem dos módulos disponíveis, conforme o passo 10, deve ser semelhante à figura que segue.
O resultado da aplicação simples construída, executada como indicado no passo 12, deve ser como na próxima figura.

Este exemplo mostrou como construir uma aplicação simples, constituída de um único módulo, com o novo sistema de modularização da plataforma Java.

Aplicação e Módulo-Recurso

Uma situação bastante mais típica é uma aplicação constituída de vários módulos. Nestes casos, sempre existe um módulo principal e outros módulos que se comportam como recursos do módulo principal.

Nesta parte do exemplo, criaremos uma aplicação, ainda no estilo clássico do "Hello World", mas que utiliza uma classe auxiliar de um pacote residente em um outro módulo, ou seja, a aplicação utiliza um módulo adicional como recurso.

1.
Navegue para o diretório inicial (Jigsaw).

2.
Crie novos subdiretórios para o novo pacote jandl.tecnopode.
md src\jandl.tecnopode\jandl\tecnopode

3.
Navegue para o subdiretório src\jandl.tecnopode\jandl\tecnopode.
cd src\jandl.tecnopode\jandl\tecnopode

4.
Neste subdiretório crie o arquivo Saudacoes.java com o conteúdo que segue.
package jandl.tecnopode;

public class Saudacoes {
   private String message;

   public Saudacoes() {
      this("Ola Jigsaw!");
   }

   public Saudacoes(String msg) {
      setMessage(msg);
   }

   public String getMessage() {
      return message;
   }

   public void setMessage(String msg) {
      message = msg;
   }

   @Override
   public String toString() {
      return getMessage();
   }
}

4.
Navegue para o subdiretório que denomina o pacote (src\jandl.tecnopode):
cd ..\..

5.
Neste subdiretório crie o arquivo module-info.java, que é o descritor do módulo jandl.tecnopode, com o conteúdo que segue.
module jandl.tecnopode {
   exports jandl.tecnopode;
}

6.
Navegue para o diretório inicial (Jigsaw).
cd ..\..

7.
Compile os arquivos do novo pacote e do descritor do módulo.
(Forneça os comandos que seguem numa única linha!)
javac -d modules\jandl.tecnopode
      src\jandl.tecnopode\jandl\tecnopode\Saudacoes.java
javac -d modules\jandl.tecnopode
      src\jandl.tecnopode\module-info.java

É possível compilar tudo junto:
javac -d modules\jandl.tecnopode
      src\jandl.tecnopode\jandl\tecnopode\Saudacoes.java
      src\jandl.tecnopode\module-info.java

8.
Verifique se o novo módulo é observável pela JVM com:
java --module-path modules --describe-module jandl.tecnopode

9.
Navegue até o diretório do subpacote src\br.gov.sp.fatec.saudacoes.
cd src\br.gov.sp.fatec.saudacoes\br\gov\sp\fatec\saudacoes

10.
Neste subdiretório crie o arquivo Main2.java, que corresponde a nova aplicação, com o conteúdo que segue.
package br.gov.sp.fatec.saudacoes;
import jandl.tecnopode.Saudacoes;

public class Main2 {
   public static void main(String[] args) {
      Saudacoes sds = new Saudacoes("Ola novamente Jigsaw!");
      System.out.println(sds);
   }
}

Observe que a classe Saudacoes, do novo pacote jandl.tecnopode, é importada como usualmente feito.

11.
Navegue para o diretório inicial (Jigsaw).
cd ..\..\..\..\..\..\..

12.
Compile a nova aplicação (Main2.java).
(O comando abaixo deve ser fornecido em uma única linha!)
javac --module-path modules
      -d modules/br.gov.sp.fatec.saudacoes
      src/br.gov.sp.fatec.saudacoes/br/gov/sp/fatec/saudacoes/Main2.java
src\br.gov.sp.fatec.saudacoes\br\gov\sp\fatec\saudacoes\Main2.java:2: error: pac
kage jandl.tecnopode is not visible
import jandl.tecnopode.Saudacoes;
            ^
  (package jandl.tecnopode is declared in module jandl.tecnopode, but module br.
gov.sp.fatec.saudacoes does not read it)
1 error

O erro obtido se deve ao fato do módulo da aplicação não ler/importar o módulo recurso.

13.
Navegue para o subdiretório inicial do pacote br.gov.sp.fatec.saudacoes.
cd src\br.gov.sp.fatec.saudacoes

14.
Edite o descritor de módulo module-info.java como segue, para indicar a importação do módulo que contém os recursos necessários.
module br.gov.sp.fatec.saudacoes {
   requires jandl.tecnopode;
}

15.
Navegue para o diretório inicial (Jigsaw).
cd ..\..\

16.
Compile novamente a nova aplicação (Main2.java) e também o descritor de seu módulo.
(O comando abaixo deve ser fornecido em uma única linha!)
javac --module-path modules
      -d modules/br.gov.sp.fatec.saudacoes
      src/br.gov.sp.fatec.saudacoes/br/gov/sp/fatec/saudacoes/Main2.java
      src/br.gov.sp.fatec.saudacoes/module-info.java

17.
Execute a nova aplicação.
(O comando abaixo deve ser fornecido em uma única linha!)
java --module-path modules
      -m br.gov.sp.fatec.saudacoes/br.gov.sp.fatec.saudacoes.Main2

O resultado da nova aplicação é como o que segue.
Ola novamente Jigsaw!

Este segundo exemplo mostrou como construir uma aplicação ainda simples, embora mais realista, pois é constituída de um módulo que utiliza recursos de outro módulo. 

Na sequência serão exploradas outras possibilidade que exibem algumas das vantagens do novo sistema de modularização.

Empacotamento dos módulos

Até agora, a compilação dos módulos construídos gerou uma árvore de subdiretórios contendo o código binário das classes distribuídos em seus respectivos subdiretórios. Em nosso projeto o subdiretório Jigsaw\src contém a árvore do código fonte dos tipos pertencentes a cada um dos módulos criados, enquanto Jigsaw\modules contém a árvore do código binário dos respectivos tipos. Claramente esta estrutura é pouco adequada para distribuição do código das aplicações.

A ferramenta de linha de comando jar, que existe desde a primeira versão do Java, foi atualizada para possibilitar a criação de módulos, ou seja, permite empacotar os tipos e descritor de um módulo na forma de um arquivo JAR.

Convém criar um novo subdiretório no projeto para conter os módulos empacotados a partir do diretório inicial (Jigsaw).
md library

Para criar um módulo, use a ferramenta jar como segue:
(O comando abaixo deve ser fornecido em uma única linha!)
jar --create
    --file=library/jandl.tecnopode@1.0.jar
    --module-version=1.0
    -C modules/jandl.tecnopode .

A opção --create é autoexplicativa; --file determina o caminho e o nome desejado para o módulo que será criado; --module-version especifica a versão do módulo; -C indica o diretório onde existe a árvore do código binário do módulo.

jar --create
    --file=library/br.gov.sp.fatec.saudacoes@1.0.jar
    --main-class=br.gov.sp.fatec.saudacoes.Main2
    -C modules/br.gov.sp.fatec.saudacoes .

Aqui deve ser observado o uso da opção --main-class seguida do nome da classe principal do módulo (aquela que é executada por padrão).

A figura que segue ilustra o resultado do empacotamento dos módulo br.gov.sp.fatec.saudacoes e jandl.tecnopode.


Com o empacotamento, a distribuição de uma aplicação se resume ao envio dos módulos necessários, que podem ser usados em qualquer outra instalação do Java 9. Para executar a aplicação, basta fornecer:
java -p library -m br.gov.sp.fatec.saudacoes

A opção -p indica uma lista de diretórios que contém os módulos necessários; enquanto -m especifica o módulo que (classe principal) terá o início executado, como mostra a figura que segue.


A ferramenta jar também pode ser usada para descrever um módulo empacotado, como exemplificado nos comandos que seguem.

jar --describe-module --file=library/jandl.tecnopode@1.0.jar
jar --describe-module --file=library/br.gov.sp.fatec.saudacoes@1.0.jar


Criação de Imagem Executável da Aplicação

Uma novidade muito interessante do Java 9 é a possibilidade de criação de imagens executáveis (runtime images) de aplicações. Uma imagem executável contém uma JVM, os módulos específicos de uma aplicação e todas as suas dependências, inclusive as transitivas (decorrentes da execução), permitindo que a aplicação seja executada em qualquer ambiente compatível, independente destes possuírem ou não instalações compatíveis do Java.

A JVM provida numa imagem executável contém apenas os módulos necessários para a aplicação, ou seja, aqueles não utilizados não são inclusos, reduzindo seu tamanho, constituindo um ambiente customizado e independente, pois não requer a presença de um JRE ou JDK para sua execução.

Apenas a arquitetura do sistema deve ser compatível, ou seja, as imagens executáveis construídas para uma arquitetura específica de SO só podem ser utilizadas em tais SOs, tal como ocorre com programas executáveis gerados para o Microsoft Windows, que não são compatíveis com SO Linux e outros.

Ainda assim, a distribuição de uma imagem executável pode simplificar muito seu uso, pois seus usuário não precisam se preocupar com os pré-requisitos de instalação necessários.

O jlink é a nova ferramenta de linha de comando capaz de criar imagens executáveis, como no exemplo de uso que segue.
(O comando abaixo deve ser fornecido em uma única linha!)
jlink --module-path %JAVA_HOME%\jmods;library
      --add-modules br.gov.sp.fatec.saudacoes
      --output jigsawDemoApp

A opção --module-path é seguida pela lista de diretórios de módulos necessários (no caso o subdiretório jmods na instalação local do Java 9 e o subdiretório library do nosso projeto). A opção --add-modules indica o módulo da aplicação que será adicionado na imagem. A opção --output indica o subdiretório onde a imagem obtida será gerada. Note que as dependências do módulo br.gov.sp.fatec.saudacoes (ou seja, os módulos java.base e jandl.tecnopode) são automaticamente identificadas e adicionadas à imagem.

A imagem gerada terá a seguinte estrutura:
jigsawDemoApp
├───bin
│   └───server
├───conf
│   └───security
│       └───policy
│           ├───limited
│           └───unlimited
├───include
│   └───win32
├───legal
│   └───java.base
└───lib
    ├───security
    └───server

Em sua raiz existe um arquivo release que contém a versão do Java e os módulos inclusos na imagem executável. No diretório lib encontramos o arquivo modules com apenas 21.8MB, bem menor que o correspondente da JVM completa da versão 9.

Para executar a aplicação encapsulada na imagem executável, basta fornecer o comando que segue:
jigsawDemoApp\bin\java -m br.gov.sp.fatec.saudacoes/br.gov.sp.fatec.saudacoes.Main2

Nele utiliza-se a JVM da própria imagem, seguida da opção -m e da combinação do nome do módulo (br.gov.sp.fatec.saudacoes), do separador '/' e do nome da classe principal  da aplicação (br.gov.sp.fatec.saudacoes.Main2).

Também é possível solicitar que a ferramenta jlink gere um pequeno script de inicialização, mais fácil de ser usado. Para criar a imagem executável e também gerar tal script, o comando adequado é:
jlink --module-path %JAVA_HOME%\jmods;library
      --add-modules br.gov.sp.fatec.saudacoes
      --output jigsawDemoApp
      --launcher launch=br.gov.sp.fatec.saudacoes/br.gov.sp.fatec.saudacoes.Main2

Observe a adição da opção --launcher launch=<modulo>/>classePrincipal>.

A ativação da aplicação agora pode ser feita de maneira bem mais simples com:
jigsawDemoApp\bin\launch

Conclusões

Os exemplos deste post, embora muito simples, mostram como utilizar de maneira proveitosa o novo sistema de modularização do Java. Em sua primeira parte mostra como criar módulos (modules). Na segunda parte mostra como construir aplicações constituídas de vários módulos.

Além disso, estes exemplo permitem perceber como a distribuição de aplicações é simplificada tanto pelo uso de módulos, como pela criação de imagens executáveis (runtime images). Módulos podem ser distribuídos diretamente, permitindo o reuso em diferentes aplicações, funcionando como componentes. No entanto o uso dos módulos requerem um ambiente de execução Java  previamente instalado. Já a distribuição de imagens executáveis é muito conveniente, pois não requerem ambientes de execução pré-instalados, pois já contém uma JVM própria. Além disso, as imagens executáveis permitem a customização das JVM para aplicações específicas, o que é algo bem interessante.

Isto tudo permite afirmar que o aguardado projeto Jigsaw e seu novo sistema de modularização é, de fato, uma valiosa adição na plataforma Java!


Para Saber Mais