Compilando o Código Java

Os plug-ins do JDT incluem um compilador Java batch e incremental para construir arquivos Java .class a partir do código fonte. Não há uma API direta fornecida pelo compilador. Ela é instalada como um construtor em projetos Java. A compilação é disparada utilizando mecanismos de construção de plataforma padrão.

Há uma descrição detalhada do mecanismo de construção da plataforma em Construtores de projetos incrementais .

Código de Compilação

É possível de maneira programática, compilar os arquivos fonte Java em um projeto que utilize a API de construção.

   IProject myProject;
IProgressMonitor myProgressMonitor;myProject.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, myProgressMonitor);

Para um projeto Java, isso chamará o construtor de projeto incremental Java (juntamente com outros construtores de projeto incrementais que tenham sido incluídos na especificação de construção do projeto). Os arquivos.class gerados são gravados na pasta de saída designada. Os arquivos de recurso adicionais também são copiados para a pasta de saída.  

No caso de uma construção em batch completa, todos os arquivos .class na pasta de saída poderão ser 'apagados' para assegurar que nenhum arquivo stale seja encontrado. Isto é controlado através do uso de uma Opção do Construtor de Núcleo do JDT (CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER).  O padrão para esta opção é limpar pastas de saída.  A menos que esta opção seja redefinida, certifique-se de colocar todos os arquivos .class, para os quais você não tenha arquivos de origem correspondentes, em uma pasta de arquivos de classe separada no classpath em vez de na pasta de saída.

Os construtores incremental e em batch podem ser configurados com outras opções que controlam quais recursos são copiados para a pasta de saída.   A amostra a seguir mostra como configurar um filtro de recursos para que arquivos que terminam com '.ignore' e pastas chamadas 'META-INF', não sejam copiados para a pasta de saída:

      Opções da tabela de hashing = JavaCore.getOptions();
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   JavaCore.setOptions(options);

Os nomes de arquivos serão filtrados se corresponderem a um dos padrões fornecidos. Pastas inteiras serão filtradas se seus nomes corresponderem a um dos nomes de pasta fornecidos que terminarem em um separador de caminho.

Os construtores incremental e em lote também podem ser configurados para gerar apenas um único erro quando o arquivo .classpath tiver erros. Esta opção é definida por padrão e elimina muitos erros.  Consulte Opções do Construtor de Núcleo do JDT para obter uma lista completa das opções relacionadas ao construtor e seus padrões.

O compilador também pode ser configurado utilizando as opções JavaCore.   Você pode definir, por exemplo, a gravidade a ser utilizada para diferentes tipos de problemas encontrados durante a compilação.   Consulte Opções do Compilador do Núcleo do JDT para obter uma lista completa de opções relacionadas ao compilador e seus padrões.

Ao configurar programaticamente as opções para o construtor ou compilador, você deve especificar o escopo da opção.  Por exemplo, a configuração de um filtro de recursos pode se aplicar a apenas um projeto específico:

   
   Hashtable options = myProject.getOptions(false);  // obter somente as opções configuradas neste projeto
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   myProject.setOptions(options);

Utilizando o Compilador de Lotes

Localizando o Compilador de Lotes

A classe do compilador de lotes está localizada nas classes internas do plug-in de Núcleo JDT. O nome da classe é org.eclipse.jdt.internal.compiler.batch.Main. Ele é empacotado em plugins/org.eclipse.jdt.core_3.2.0.jar. Desde o 3.2, ele também está disponível como um download separado. O nome do arquivo é ecj.jar. Sua origem correspondente também está disponível. Para obtê-los, vá para a página de download e procure pela seção Compilador de Lotes de Núcleo do JDT. Esse jar contém o compilador de lotes e o adaptador ant javac.

Portanto, ele pode ser utilizado como um aplicativo independente e dentro de um build de Ant, fora do Eclipse.

Executando o Compilador de Lotes

Quais Opções Estão Disponíveis?

Com o segundo plano laranja, estas são as opções sugeridas.

Nome Uso
Opções de caminhos de classes
-bootclasspath <dir 1>;<dir 2>;...;<dir P> Esta é uma lista de diretórios ou arquivos jar utilizados para auto-inicialização dos arquivos de classe utilizados pelo compilador. Por padrão, as bibliotecas do VM em execução são utilizadas. As entradas são separadas pelo separador de caminhos da plataforma.
Cada diretório ou arquivo pode especificar regras de acesso para tipos entre '[' e ']'.
-cp
-classpath <dir 1>;<dir 2>;...;<dir P>
Esta é uma lista de diretórios ou arquivos jar utilizados para compilar os arquivos de origem. O valor padrão é o valor da propriedade "java.class.path". As entradas são separadas pelo separador de caminhos da plataforma.
Cada diretório ou arquivo pode especificar regras de acesso para tipos entre '[' e ']' (por ex., [-X] para proibir acesso ao tipo X, [~X] para desestimular acesso ao tipo X, [+p/X:-p/*] para proibir acesso a todos os tipos no pacote p, mas permitir acesso a p/X).
-extdirs <dir 1>;<dir 2>;...;<dir P> Esta é uma lista de diretórios utilizados para especificar o local de arquivos de extensão zip/jar. As entradas são separadas pelo separador de caminhos da plataforma.
-endorseddirs <dir 1>;<dir 2>;...;<dir P> Esta é uma lista de diretórios utilizados para especificar o local de arquivos endossados zip/jar. As entradas são separadas pelo separador de caminhos da plataforma.
-sourcepath <dir 1>;<dir 2>;...;<dir P> Esta é uma lista de diretórios utilizados para especificar os arquivos de origem. As entradas são separadas pelo separador de caminhos da plataforma.
Cada diretório pode especificar regras de acesso para tipos entre '[' e ']'.
-d <dir 1>|none Isso é utilizado para especificar em qual diretório os arquivos .class gerados devem ser despejados. Se ele for omitido, nenhuma estrutura de diretório do pacote será criada.
Se você não desejar gerar nenhum arquivo .class, utilize -d none.
-encoding <nome da codificação> Especifique o formato de codificação de origem padrão (a codificação customizada também pode ser especificada por arquivo, sufixando cada nome de arquivo/pasta de origem de entrada com [<nome da d>], por exemplo X.java[utf8]).
Opções de Conformidade
-target 1.1|1.2|1.3|1.4|1.5|5|5.0|1.6|6|6.0 Isso especifica a configuração de destino do arquivo .class. O valor possível é:
  • 1.1 (versão principal: 45 secundária: 3)
  • 1.2 (versão principal: 46 secundária: 0)
  • 1.3 (versão principal: 47 secundária: 0)
  • 1.4 (versão principal: 48 secundária: 0)
  • 1.5, 5 ou 5.0 (versão principal: 49 secundária: 0)
  • 1.6, 6 ou 6.0 (versão principal: 50 secundária: 0)
Os padrões são:
  • 1.1 no modo -1.3
  • 1.2 no modo -1.4
  • 1.5 no modo -1.5
  • 1.6 no modo -1.6
-1.3 Configure o nível de conformidade como 1.3. -origem 1.3 -destino 1.1 implícitos.
-1.4 Configure o nível de conformidade como 1.4 (padrão). -origem 1.3 -destino 1.2 implícitos.
-1.5 Configure o nível de conformidade como 1.5. -origem 1.5 -target 1.5 implícitos.
-1.6 Configure o nível de conformidade como 1.6. Implícito -source 1.6 -target 1.6.
-source 1.3|1.4|1.5|5|5.0|1.6|6|6.0 Utilizado para especificar o nível de origem esperado pelo compilador.
O valor possível é:
  • 1.3
  • 1.4
  • 1.5, 5 ou 5.0
  • 1.6, 6 ou 6.0
Os padrões são:
  • 1.3 no modo -1.3
  • 1.3 no modo -1.4
  • 1.5 no modo -1.5
  • 1.6 no modo -1.6
Em 1.4, assert é tratado como uma palavra-chave. No 1.5 e 1.6, enum e assert são tratados como palavras-chave.
Opções de Aviso
-warn:
allDeprecation
allJavadoc
assertIdentifier
boxing
charConcat
conditionAssign
constructorName
dep-ann
deprecation
discouraged
emptyBlock
enumSwitch
fallthrough
fieldHiding
finalBound
finally
forbidden
hiding
incomplete-switch
indirectStatic
intfAnnotation
intfNonInherited
javadoc
localHiding
maskedCatchBlocks
nls
noEffectAssign
null
over-ann
paramAssign
pkgDefaultMethod
raw
semicolon
serial
specialParamHiding
static-access
staticReceiver
suppress
synthetic-access
syntheticAccess
tasks(<task1>|...|<taskN>)
typeHiding
desmarcada,
unnecessaryElse
unqualified-field-access
unqualifiedField
unused
unusedArgument
unusedImport
unusedLabel
unusedLocal
unusedPrivate
unusedThrown
uselessTypeCheck
varargsCast
warningToken
Configure o nível de aviso.
Por exemplo, -warn:unusedLocal,deprecation

Em red são as configurações padrão.

    -warn:none                               disable all warnings
    -warn:<warnings separated by ,>    enable exactly the
listed warnings
    -warn:+<warnings separated by ,>   enable additional
warnings
    -warn:-<warnings separated by ,>   disable specific
warnings
allDeprecation substituição mesmo dentro do código substituído
allJavadoc javadoc inválido ou ausente
assertIdentifier ocorrência de assert utilizada como identificador
boxing conversão do autoboxing
charConcat quando uma matriz de caracteres é utilizada em uma concatenação de cadeia sem estar convertida explicitamente para uma cadeia
conditionAssign possível designação do booleano acidental
constructorName método com nome de construtor
dep-ann anotação do @Deprecated ausente
deprecation o uso de tipo ou membro substituído fora do código substituído
discouraged o uso de tipos correspondentes a uma regra de acesso desestimulada
emptyBlock bloco vazio não documentado
enumSwitch,
incomplete-switch
comutador enum incompleto
fallthrough possível caso de fall-through
fieldHiding campo ocultando outra variável
finalBound parâmetro type com limite final
finally bloco finally não é concluído de modo normal
forbidden o uso de tipos correspondentes a uma regra de acesso proibida
hiding macro para fieldHiding, localHiding, typeHiding e maskedCatchBlock
indirectStatic referência indireta para membro estático
intfAnnotation tipo de anotação utilizada como super interface
intfNonInherited compatibilidade de método não-herdado da interface
javadoc javadoc inválido
localHiding variável local ocultando outra variável
maskedCatchBlocks bloco catch oculto
nls literais de cadeia não-nls (falta de tags //$NON-NLS-<n>)
noEffectAssign designação sem efeito
null verificação nula ausente ou redundante
over-ann anotação @Override ausente
paramAssign designação a um parâmetro
pkgDefaultMethod tentativa de substituir método de pacote padrão
raw uso de um tipo bruto (em vez de um tipo parametrizado)
semicolon semicolon desnecessário ou instrução vazia
serial serialVersionUID ausente
specialParamHiding parâmetro construtor ou definidor ocultando outro campo
static-access macro para indirectStatic e staticReceiver
staticReceiver se um receptor não estático for utilizado para obter um campo estático ou chamar um método estático
suppress ativar @SuppressWarnings
syntheticAccess,
synthetic-access
quando executar acesso sintético para innerclass
tasks ative suporte para tags de tarefas no código fonte
typeHiding parâmetro type ocultando outro tipo
unchecked operação de tipo desmarcada
unnecessaryElse desnecessária cláusula else
acesso ao campo não qualificado,
unqualifiedField
referência não qualificada para campo
unused macro para unusedArgument, unusedImport, unusedLabel, unusedLocal, unusedPrivate e unusedThrown
unusedArgument argumento de método não utilizado
unusedImport referência de importação não utilizada
unusedLabel rótulo não utilizado
unusedLocal variável local não utilizada
unusedPrivate declaração de membro privado não utilizada
unusedThrown exceção emitida declarada não utilizada
uselessTypeCheck operação de coerção/instância desnecessária
varargsCast argumento varargs precisa de coerção explícita
warningToken token de aviso não tratado em @SuppressWarnings

-nowarn Nenhum aviso (equivalente a -warn:none)
-deprecation Equivalente a -warn:deprecation.
Opções de Depuração
-g[:none|:lines,vars,source] Configure o nível de atributos de depuração
-g Todas as informações sobre depuração (equivalente a -g:lines,vars,source)
-g:none Nenhuma informação sobre depuração
-g:[lines,vars,source] informações de depuração seletiva
-preserveAllLocals Explicitamente peça ao compilador para preservar todas as variáveis locais (para fins de depuração). Se omitido, o compilador removerá os locais não utilizados.
Opções Ignoradas (para Compatibilidade com Opções javac)
-J<opção> opção de transmissão para a máquina virtual
-X<opção> especifica uma opção não padrão. -Xemacs não é ignorado.
-X imprimir opções não padrão e sair
-O otimizar para tempo de execução
Opções Avançadas
@<arquivo> Mostre os argumentos da linha de comandos a partir do arquivo
-maxProblems <n> Número máximo de problemas por unidade de compilação (100 por padrão)
-log <nome do arquivo> Especifique um arquivo de registros no qual todas as saídas do compilador serão despejadas. Isso será realmente útil se você desejar depurar o compilador de batch ou obter um arquivo que contenha todos os erros e avisos a partir de uma construção de batch. Se a extensão for .xml, o registro gerado será um arquivo xml.
-Xemacs Utilize o estilo emacs para apresentar locais de erros e avisos nos registros de texto comum e do console. Os registros XML não são afetados por essa opção. Com essa opção ativa, a mensagem:
2. AVISO em /workspace/X.java
(na linha 8)...

é apresentada como:
/workspace/X.java:8: aviso: O método...
-proceedOnError Manter a compilação apesar dos erros, efetuando dump de arquivos de classe com métodos de problemas ou tipos de problemas. Será recomendável apenas se você puder executar o aplicativo mesmo se tiver erros restantes.
-verbose Imprima unidades de compilação acessadas/processadas no console ou no arquivo de registros, se especificado.
-referenceInfo Compute informações sobre referência. Isso será útil apenas se estiver conectado com o construtor. Caso contrário, as informações sobre referência serão inúteis.
-progress Mostrar progresso (apenas no modo -log).
-time Exibir informações de velocidade.
-noExit Não chamar System.exit(n) no final da compilação (n=0 se não houver nenhum erro).
-repeat <n> Repita as vezes do processo de compilação do <n> (análise de desempenho).
-inlineJSR Bytecode JSR seqüencial (implícito se o destino >= 1.5).
-enableJavadoc Considerar referências no javadoc.
Opções de Ajuda
-? -help Exibe a mensagem de ajuda.
-v -version Exiba a número de construção do compilador. Isso é muito útil para relatar um erro.
-showversion Exiba o número de construção do compilador e continue. Isso é muito útil para relatar um erro.

Exemplos

d:\temp -classpath rt.jar -time -g -d d:/tmp Ele compila todos os arquivos de origem no d:\temp e suas subpastas. O caminho de classe é simplesmente rt.jar. Ele gera todos os atributos de depuração e todos os arquivos .class são despejados em d:\tmp. A velocidade do compilador será exibida quando o processo de batch for concluído.
d:\temp\Test.java -classpath d:\temp;rt.jar -g:none Ele compila apenas o Test.java e seus arquivos dependentes, se houver algum, recuperando os arquivos dependentes do d:\temp. O caminho de classe é d:\temp seguido por rt.jar, o que significa que todas as classes necessárias são procuradas primeiramente no d:\temp e, depois, no rt.jar. Não gera atributos de depuração e efetua dump de todos os arquivos .class gerados em d:\temp.

Utilizando o Adaptador Ant Javac

O compilador Eclipse pode ser utilizado dentro do script Ant utilizando o adaptador javac. Para utilizar o compilador Eclipse, será necessário apenas definir a propriedade build.compiler em seu script. A seguir, um pequeno exemplo.
<?xml version="1.0" encoding="UTF-8"?>
<project name="compile" default="main" basedir="../.">

	<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>

	<property name="root" value="${basedir}/src"/>

	<property name="destdir" value="d:/temp/bin" />

	<target name="main">
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
		    <classpath>
		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
		    </classpath>
		</javac>		
	</target>
</project>
A sintaxe utilizada para a tarefa javac Ant pode ser encontrada na documentação da tarefa Ant javac . O adaptador atual suporta a tarefa Javac Ant 1.4.1 até as versões 1.6.5.

Se estiver utilizando uma versão acima de 1.5.0, será possível utilizar o elemento do argumento do compilador aninhado para especificar opções específicas ao compilador.

...
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
		    <classpath>
		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
		    </classpath>
    <compilerarg
compiler="org.eclipse.jdt.core.JDTCompilerAdapter"
line="-1.5 -warn:+boxing"/>
</javac>		
...

Para evitar a obtenção de scripts dependentes do compilador, é aconselhável utilizar o argumento do compilador configurado como org.eclipse.jdt.core.JDTCompilerAdapter. Se isso não estiver configurado, o script poderá ser utilizado apenas com o compilador do Eclipse. Se estiver configurado, o argumento do compilador aninhado será ignorado se o nome for diferente do nome do compilador especificado pela propriedade build.compiler.

Determinação de Problemas

O Núcleo do JDT define um marcador especializado (tipo de marcador "org.eclipse.jdt.core.problem ") para indicar problemas de compilação. Para descobrir os problemas detectados pelo compilador de maneira programática, deve-se utilizar o protocolo de marcador de plataforma padrão. Consulte Marcadores de Recursos para obter uma visão geral da utilização de marcadores.

O seguinte trecho procura todos os marcadores de problemas Java em uma unidade de compilação.

   public IMarker[] findJavaProblemMarkers(ICompilationUnit cu)          throws CoreException {
IResource javaSourceFile = cu.getUnderlyingResource();IMarker[] markers = javaSourceFile.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,true, IResource.DEPTH_INFINITE);   }

Os marcadores de problemas Java são mantidos pelo construtor de projeto Java e são removidos automaticamente à medida que os problemas são resolvidos e a origem Java é recompilada.

O valor do ID do problema é configurado para uma das constantes definidas em IProblem . O id do problema é confiável, mas a mensagem é localizada e, portanto, pode ser alterada de acordo com o locale padrão. As constantes definidas em IProblem são autodescritivas.

Uma implementação de IProblemRequestor deve ser definida para coletar os problemas descobertos durante uma operação Java. As cópias de trabalho poderão ser reconciliadas com a detecção de problemas se um IProblemRequestor tiver sido fornecido para a criação da cópia de trabalho. Para conseguir isso, você pode utilizar o método reconcile.Este é um exemplo:

  ICompilationUnit unit = ..; // obter alguma unidade de compilação
			
  // criar solicitante para acumular problemas descobertos
  IProblemRequestor problemRequestor = new IProblemRequestor() {
    public void acceptProblem(IProblem problem) {
      System.out.println(problem.getID() + ": " + problem.getMessage());
    }
    public void beginReporting() {}
    public void endReporting() {}
    public boolean isActive() {	return true; } // detectará problemas se ativo
  };
    
  // utilizar cópia de trabalho para reter origem com erro
  ICompilationUnit workingCopy = unit.getWorkingCopy(new WorkingCopyOwner() {}, problemRequestor, null);
  ((IOpenable)workingCopy).getBuffer().setContents("public class X extends Zork {}");

  // reconciliação do disparo
  workingCopy.reconcile(NO_AST, true, null, null);
Você pode incluir uma ação sobre os problemas relatados no método acceptProblem(IProblem). Neste exemplo, o problema relatado será que Zork não pode ser resolvido ou não é uma superclasse válida e seu id é IProblem.SuperclassNotFound .

Excluindo Avisos Utilizando SuppressWarnings

O Java 5.0 oferece ao usuário a opção de desativar os avisos de compilação relativos a um subconjunto de uma unidade de compilação que utiliza a anotação java.lang.SuppressWarning.

	@SuppressWarning("unused") public void foo() {
		String s;
	}

Sem a anotação, o compilador reclamaria de que a variável local s nunca é utilizada. Com a anotação, o compilador ignora de modo silencioso esse aviso localmente no método foo. Isso permite manter os avisos em outros locais da mesma unidade de compilação ou do mesmo projeto.

A lista de tokens que podem ser utilizados em uma anotação SuppressWarning é: