Versões Java em builds do Android

Não importa se o código-fonte foi escrito em Java, Kotlin ou ambos, há vários lugares em que você precisa escolher uma versão da linguagem JDK ou Java para o build.

Visão geral das relações do JDK em um build do Gradle

Glossário

Kit de desenvolvimento em Java (JDK)
O Kit de desenvolvimento em Java (JDK) contém:
  • Ferramentas, como compilador, criador de perfil e criador de arquivos. Eles são usados em segundo plano durante a criação do aplicativo.
  • Bibliotecas contendo APIs que você pode chamar do código-fonte Kotlin ou Java. Nem todas as funções estão disponíveis no Android.
  • A máquina virtual Java (JVM), um intérprete que executa aplicativos Java. Use a JVM para executar o ambiente de desenvolvimento integrado do Android Studio e a ferramenta de build do Gradle. A JVM não é usada em dispositivos ou emuladores Android.
Ambiente de execução do JetBrains (JBR) (link em inglês)
O JetBrains Runtime (JBR) é um JDK aprimorado, distribuído com o Android Studio. Ela inclui várias otimizações para uso no Studio e em produtos JetBrains relacionados, mas também pode ser usado para executar outros aplicativos Java.

Como escolho um JDK para executar o Android Studio?

Recomendamos que você use o JBR para executar o Android Studio. Ele é implantado e usado para testar o Android Studio e inclui melhorias para o uso ideal do Android Studio. Para garantir isso, não defina a variável de ambiente STUDIO_JDK.

Os scripts de inicialização do Android Studio procuram uma JVM na seguinte ordem:

  1. Variável de ambiente STUDIO_JDK
  2. Diretório studio.jdk (na distribuição do Android Studio)
  3. jbr (ambiente de execução do JetBrains) na distribuição do Android Studio. Recomendado
  4. Variável de ambiente JDK_HOME
  5. Variável de ambiente JAVA_HOME
  6. java executável na variável de ambiente PATH

Como faço para escolher qual JDK executa meus builds do Gradle?

Se você executar o Gradle usando os botões no Android Studio, o JDK definido nas configurações do Android Studio será usado para executar o Gradle. Se você executar o Gradle em um terminal, dentro ou fora do Android Studio, a variável de ambiente JAVA_HOME (se definida) vai determinar qual JDK executará os scripts do Gradle. Se JAVA_HOME não estiver definido, ele usará o comando java na variável de ambiente PATH.

Para resultados mais consistentes, defina a variável de ambiente JAVA_HOME e a configuração do Gradle JDK no Android Studio para o mesmo JDK.

Ao executar o build, o Gradle cria um processo chamado daemon para executar o build em si. Esse processo pode ser reutilizado, desde que os builds estejam usando a mesma versão do JDK e Gradle. A reutilização de um daemon reduz o tempo para iniciar uma nova JVM e inicializar o sistema de build.

Se você iniciar builds com diferentes versões do JDK ou do Gradle, outros daemons serão criados, consumindo mais CPU e memória.

Configuração do Gradle JDK no Android Studio

Para modificar a configuração do Gradle JDK do projeto existente, abra as configurações do Gradle em File (ou Android Studio no macOS) > Settings > Build, Execution, Deployment > Build Tools > Gradle. O menu suspenso Gradle JDK contém as seguintes opções para seleção:

  • Macros como JAVA_HOME e GRADLE_LOCAL_JAVA_HOME
  • Entradas da tabela JDK no formato vendor-version, como jbr-17, que são armazenadas nos arquivos de configuração do Android.
  • Como fazer o download de um JDK
  • Como adicionar um JDK específico
  • JDKs detectados localmente no diretório de instalação padrão do JDK do sistema operacional

A opção selecionada é armazenada na opção gradleJvm no arquivo .idea/gradle.xml do projeto, e a resolução do caminho do JDK é usada para executar o Gradle quando iniciado pelo Android Studio.

Figura 1. Configurações do Gradle JDK no Android Studio.

As macros ativam a seleção dinâmica de caminho do JDK do projeto:

  • JAVA_HOME: usa a variável de ambiente com o mesmo nome
  • GRADLE_LOCAL_JAVA_HOME: usa a propriedade java.home no arquivo .gradle/config.properties, que usa o ambiente de execução do JetBrains por padrão.

O JDK selecionado é usado para executar o build do Gradle e resolver as referências da API JDK ao editar os scripts de build e o código-fonte. Observe que o compileSdk especificado vai restringir ainda mais quais símbolos Java estarão disponíveis ao editar e criar seu código-fonte.

Escolha uma versão do JDK anterior ou igual às versões do JDK usadas pelos plug-ins usados no build do Gradle. Para determinar a versão mínima necessária do JDK para o Plug-in do Android para Gradle (AGP, na sigla em inglês), consulte a tabela de compatibilidade nas notas da versão.

Por exemplo, o Plug-in do Android para Gradle versão 8.x requer o JDK 17. Se você tentar executar um build do Gradle que o use com uma versão anterior do JDK, ele vai informar uma mensagem como esta:

An exception occurred applying plugin request [id: 'com.android.application']
> Failed to apply plugin 'com.android.internal.application'.
   > Android Gradle plugin requires Java 17 to run. You are currently using Java 11.
      Your current JDK is located in /usr/local/buildtools/java/jdk11
      You can try some of the following options:
       - changing the IDE settings.
       - changing the JAVA_HOME environment variable.
       - changing `org.gradle.java.home` in `gradle.properties`.

Quais APIs Java posso usar no meu código-fonte em Java ou Kotlin?

Um aplicativo Android pode usar algumas das APIs definidas em um JDK, mas não todas todas. O SDK do Android define implementações de muitas funções da biblioteca Java como parte das APIs disponíveis. A propriedade compileSdk especifica qual versão do SDK do Android usar ao compilar o código-fonte em Kotlin ou Java.

Kotlin

android {
    ...
    compileSdk = 33
}

Groovy

android {
    ...
    compileSdk 33
}

Cada versão do Android é compatível com uma versão específica do JDK e um subconjunto de APIs Java disponíveis. Se você usa uma API Java disponível em um compileSdk que não está no minSdk especificado, pode ser possível usar a API na versão anterior do Android com um processo conhecido como simplificação. Consulte APIs Java 11+ disponíveis pela simplificação para APIs com suporte.

Use esta tabela para determinar qual versão do Java é compatível com cada API do Android e onde encontrar detalhes sobre quais APIs Java estão disponíveis.

Android Java Recursos de linguagem e API compatíveis
14 (API 34). 17 Bibliotecas principais
13 (API 33). 11 Bibliotecas principais
12 (API 32). 11 API Java
11 e anteriores Versões do Android

Qual JDK compila meu código-fonte em Java?

O conjunto de ferramentas Java JDK contém o compilador Java usado para criar qualquer código-fonte Java. Esse JDK também executa o compilador Kotlin (executado em uma JVM), o javadoc e os testes são executados durante o build.

O conjunto de ferramentas assume como padrão o JDK usado para executar o Gradle. Se você usar o padrão e executar um build em máquinas diferentes (por exemplo, na máquina local e em um servidor de integração contínua separado), os resultados do build poderão ser diferentes se outras versões do JDK forem usadas.

Para criar uma compilação mais consistente, especifique explicitamente uma versão do conjunto de ferramentas Java. Especificar:

  • Localiza um JDK compatível no sistema que executa o build.
    • Se não houver um JDK compatível e um resolvedor de conjunto de ferramentas estiver definido, faça o download de um.
  • Expõe as APIs Java do conjunto de ferramentas para chamadas do código-fonte.
  • Compila a origem Java usando a versão da linguagem Java.
  • O padrão de envio é sourceCompatibility e targetCompatibility.

Recomendamos que você sempre especifique o conjunto de ferramentas Java e verifique se o JDK especificado está instalado ou adicione um resolvedor de conjunto de ferramentas ao build.

Você pode especificar o conjunto de ferramentas independentemente de o código-fonte ser escrito em Java, Kotlin ou ambos. Especifique o conjunto de ferramentas no nível superior do arquivo build.gradle(.kts) do módulo.

Se o código-fonte for escrito apenas em Java, especifique a versão do conjunto de ferramentas Java desta forma:

Kotlin

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

Groovy

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

Se a origem for apenas em Kotlin ou uma combinação de Kotlin e Java, especifique a versão do conjunto de ferramentas Java desta forma:

Kotlin

kotlin {
    jvmToolchain(17)
}

Groovy

kotlin {
    jvmToolchain 17
}

A versão do JDK do conjunto de ferramentas pode ser a mesma usada para executar o Gradle, mas elas têm finalidades diferentes.

Quais recursos de origem da linguagem Java posso usar no meu código-fonte Java?

A propriedade sourceCompatibility determina quais recursos da linguagem Java estão disponíveis durante a compilação da origem Java. Isso não afeta a origem Kotlin.

Se não for especificado, o padrão será o conjunto de ferramentas Java ou JDK usado para executar o Gradle. Recomendamos que você sempre especifique explicitamente um conjunto de ferramentas (preferencial) ou sourceCompatibility.

Especifique sourceCompatibility no arquivo build.gradle(.kts) do módulo.

Kotlin

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
    }
}

Groovy

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

Quais recursos binários Java podem ser usados ao compilar meu código-fonte em Kotlin ou Java?

Especificar targetCompatibility e jvmTarget determina a versão de formato de classe Java usada ao gerar bytecode para a fonte Java e Kotlin compilada, respectivamente.

Alguns recursos do Kotlin existiam antes da adição dos recursos Java equivalentes. Os primeiros compiladores Kotlin precisavam criar a própria maneira de representar esses recursos do Kotlin. Alguns desses recursos foram adicionados posteriormente ao Java. Com os níveis jvmTarget mais recentes, o compilador Kotlin pode usar diretamente o recurso Java, o que pode resultar em um melhor desempenho.

targetCompatibility tem o mesmo valor de sourceCompatibility por padrão, mas precisa ser maior ou igual a sourceCompatibility, se especificado.

O padrão de jvmTarget é a versão do conjunto de ferramentas.

Diferentes versões do Android são compatíveis com diferentes versões do Java. Você pode aproveitar outros recursos Java aumentando targetCompatibility e jvmTarget, mas isso pode forçar você a também aumentar a versão mínima do SDK do Android para garantir que o recurso esteja disponível.

Kotlin

android {
    compileOptions {
        targetCompatibility = JavaVersion.VERSION_17
    }
    kotlinOptions {
        jvmTarget = "17"
    }
}

Groovy

android {
    compileOptions {
        targetCompatibility JavaVersion.VERSION_17
    }
    kotlinOptions {
        jvmTarget '17'
    }
}