Qual é o sinalizador --release no compilador Java 9?

89

O Java 9 javactem um novo sinalizador --release:

> javac --help
...

--release <release>
    Compile for a specific VM version. Supported targets: 6, 7, 8, 9

Como é diferente de -sourcee -targetsinalizadores? É apenas um atalho para -source X -target X?

ZhekaKozlov
fonte

Respostas:

113

Não exatamente.

JEP 247: Compile for Older Platform Versions define esta nova opção de linha de comando--release:

Definimos uma nova opção de linha de comando --release, que configura automaticamente o compilador para produzir arquivos de classe que serão vinculados a uma implementação da versão de plataforma fornecida. Para as plataformas predefinidas em javac, --release Né equivalente a-source N -target N -bootclasspath <bootclasspath-from-N> . (ênfase minha)

Então não, não é equivalente a -source N -target N. O motivo desta adição é declarado na seção "Motivação":

javacfornece duas opções de linha de comando -sourcee -target, que podem ser usadas para selecionar a versão da linguagem Java aceita pelo compilador e a versão dos arquivos de classe que ele produz, respectivamente. Por padrão, entretanto, javaccompila com a versão mais recente das APIs da plataforma. O programa compilado pode, portanto, usar acidentalmente APIs disponíveis apenas na versão atual da plataforma. Esses programas não podem ser executados em versões anteriores da plataforma, independentemente dos valores passados ​​para -sourcee -target. opções. Este é um ponto problemático de usabilidade de longo prazo, uma vez que os usuários esperam que, ao usar essas opções, obtenham arquivos de classe que podem ser executados na versão de plataforma especificada.

Resumindo, especificar as opções de origem e destino não são suficientes para compilação cruzada. Como javac, por padrão, compila com base nas APIs mais recentes da plataforma, não é possível garantir que sejam executados em versões mais antigas. Você também precisa especificar a -bootclasspathopção correspondente à versão mais antiga para fazer a compilação cruzada corretamente. Isso incluiria a versão correta da API para compilar e permitir a execução na versão mais antiga. Como era esquecido com frequência, foi decidido adicionar uma opção de linha de comando que fazia todas as coisas necessárias para uma compilação cruzada correta.

Leituras adicionais na lista de discussão e Oracle Docs . O bug original foi arquivado aqui . Observe que, desde a integração desta opção, as compilações JDK vêm agrupadas com descrições das APIs da plataforma de versões mais antigas, mencionadas na seção "Riscos e suposições". Isso significa que você não precisa da versão mais antiga instalada em sua máquina para que a compilação cruzada funcione.

Andrew Li
fonte
uma dúvida, seria possível usar recursos do jdk 9-11 no código e ainda rodar no java runtime 8?
Cristiano
Não, eles não estariam presentes no binário jre 8
Rogue
O que vocês chamam de "API de plataforma"? Algo está no nível do código de byte? ou algo relacionado à plataforma x86 subjacente ou APIs do sistema operacional?
José Cifuentes
2
@JoseCifuentes, "API da plataforma" aqui recebe a API do JDK, sua versão, sem o --releasesinalizador, seria inferida do JDK usado para compilar, que geralmente difere do JDK que você usa -sourcee -target. Isso pode incomodá-lo no caso de você usar classes / métodos introduzidos no JDK, nunca naquele que você almeja. Isso é muito sutil no caso de o compilador escolher uma sobrecarga de método que foi adicionada em uma versão posterior sobre a anterior que você pretendia, quebrando silenciosamente a compatibilidade binária.
Oliver Gondža,
30

--release Xé mais do que apenas um atalho para -source X -target Xporque -sourcee -targetnão são suficientes para compilar com segurança para uma versão mais antiga. Você também precisa definir um -bootclasspathsinalizador que deve corresponder à versão mais antiga (e esse sinalizador é frequentemente esquecido). Assim, em Java 9 eles fizeram uma única --releasebandeira que é um substituto para três bandeiras: -source, -targete-bootclasspath .

Portanto, este é um exemplo de compilação para Java 1.7:

javac --release 7 <source files>

Observe que você nem precisa ter o JDK 7 instalado em seu computador. O JDK 9 já contém as informações necessárias para evitar que você se vincule acidentalmente a símbolos que não existiam no JDK 7.

ZhekaKozlov
fonte