Android 빌드의 Java 버전

소스 코드가 Java, Kotlin 또는 두 가지 모두로 작성되었는지에 관계없이 빌드에 JDK 또는 Java 언어 버전을 선택해야 하는 위치가 여러 개 있습니다.

Gradle 빌드의 JDK 관계 개요
그림 1. 빌드의 JDK 관계

용어집

JDK(Java Development Kit)
Java 개발 키트 (JDK)에는 다음이 포함됩니다.
  • 컴파일러, 프로파일러, 보관 파일 작성기와 같은 도구 이는 애플리케이션을 만들기 위해 빌드 중에 백그라운드에서 사용됩니다.
  • Kotlin 또는 Java 소스 코드에서 호출할 수 있는 API가 포함된 라이브러리입니다. Android에서는 일부 함수를 사용할 수 없습니다.
  • Java 애플리케이션을 실행하는 인터프리터인 Java 가상 머신(JVM) JVM을 사용하여 Android 스튜디오 IDE와 Gradle 빌드 도구를 실행합니다. JVM은 Android 기기나 에뮬레이터에서 사용되지 않습니다.
JetBrains 런타임 (JBR)
JetBrains 런타임(JBR)은 Android 스튜디오와 함께 배포되는 향상된 JDK입니다. 스튜디오 및 관련 JetBrains 제품에서 사용할 수 있는 여러 최적화가 포함되어 있지만 다른 Java 애플리케이션을 실행하는 데도 사용할 수 있습니다.

Android 스튜디오를 실행하기 위해 JDK를 선택하려면 어떻게 해야 하나요?

JBR을 사용하여 Android 스튜디오를 실행하는 것이 좋습니다. 이 라이브러리는 Android 스튜디오와 함께 배포 및 테스트되는 데 사용되며 최적의 Android 스튜디오 사용을 위한 개선사항이 포함되어 있습니다. 이렇게 하려면 STUDIO_JDK 환경 변수를 설정하지 마세요.

Android 스튜디오의 시작 스크립트는 다음 순서로 JVM을 찾습니다.

  1. STUDIO_JDK 환경 변수
  2. studio.jdk 디렉터리(Android 스튜디오 배포 내)
  3. jbr 디렉터리 (JetBrains Runtime)에 저장됩니다. (권장)
  4. JDK_HOME 환경 변수
  5. JAVA_HOME 환경 변수
  6. PATH 환경 변수의 java 실행 파일

Gradle 빌드를 실행할 JDK를 선택하려면 어떻게 해야 하나요?

Android 스튜디오의 버튼을 사용하여 Gradle을 실행하는 경우 Android 스튜디오 설정에 설정된 JDK를 사용하여 Gradle을 실행합니다. Android 스튜디오 안팎의 터미널에서 Gradle을 실행하는 경우 JAVA_HOME 환경 변수(설정된 경우)에 따라 Gradle 스크립트를 실행하는 JDK가 결정됩니다. JAVA_HOME가 설정되어 있지 않으면 PATH 환경 변수에서 java 명령어를 사용합니다.

가장 일관된 결과를 얻으려면 JAVA_HOME 환경 변수와 Android 스튜디오의 Gradle JDK 구성을 동일한 JDK로 설정해야 합니다.

빌드를 실행할 때 Gradle은 실제 빌드를 실행하는 데몬이라는 프로세스를 만듭니다. 빌드에서 동일한 JDK 및 Gradle 버전을 사용하는 한 이 프로세스를 재사용할 수 있습니다. 데몬을 재사용하면 새 JVM을 시작하고 빌드 시스템을 초기화하는 데 걸리는 시간이 줄어듭니다.

다른 JDK 또는 Gradle 버전으로 빌드를 시작하면 추가 데몬이 생성되어 CPU와 메모리를 더 많이 사용합니다.

Android 스튜디오의 Gradle JDK 구성

기존 프로젝트의 Gradle JDK 구성을 수정하려면 File(macOS의 경우 Android 스튜디오) > Settings > Build, Execution, Deployment > Build Tools > Gradle에서 Gradle 설정을 엽니다. Gradle JDK 드롭다운에는 다음과 같은 옵션이 포함되어 있습니다.

  • JAVA_HOME, GRADLE_LOCAL_JAVA_HOME 등의 매크로
  • Android 구성 파일에 저장되는 jbr-17과 같은 vendor-version 형식의 JDK 테이블 항목
  • JDK 다운로드
  • 특정 JDK 추가
  • 운영체제의 기본 JDK 설치 디렉터리에서 로컬로 감지된 JDK

선택한 옵션은 프로젝트의 .idea/gradle.xml 파일의 gradleJvm 옵션에 저장되며, JDK 경로 확인은 Android 스튜디오를 통해 시작할 때 Gradle을 실행하는 데 사용됩니다.

그림 2. Android 스튜디오의 Gradle JDK 설정

매크로를 사용하면 동적 프로젝트 JDK 경로 선택을 사용 설정할 수 있습니다.

  • JAVA_HOME: 동일한 이름의 환경 변수를 사용합니다.
  • GRADLE_LOCAL_JAVA_HOME: .gradle/config.properties 파일의 java.home 속성을 사용하며 기본값은 JetBrains 런타임입니다.

선택한 JDK는 Gradle 빌드를 실행하고 빌드 스크립트와 소스 코드를 수정할 때 JDK API 참조를 확인하는 데 사용됩니다. 지정된 compileSdk는 소스 코드를 수정하고 빌드할 때 사용할 수 있는 Java 기호를 추가로 제한합니다.

Gradle 빌드에서 사용하는 플러그인에서 사용하는 JDK 버전보다 크거나 같은 JDK 버전을 선택해야 합니다. Android Gradle 플러그인(AGP)에 필요한 최소 JDK 버전을 확인하려면 출시 노트의 호환성 표를 참고하세요.

예를 들어 Android Gradle 플러그인 버전 8.x에는 JDK 17이 필요합니다. 이전 버전의 JDK에서 이 빌드를 사용하는 Gradle 빌드를 실행하려고 하면 다음과 같은 메시지가 보고됩니다.

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/jdk
      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`.

Java 또는 Kotlin 소스 코드에서 사용할 수 있는 Java API는 무엇인가요?

Android 애플리케이션은 JDK에 정의된 일부 API를 사용할 수 있지만 전체 API는 사용할 수 없습니다. Android SDK는 사용 가능한 API의 일부로 많은 Java 라이브러리 함수의 구현을 정의합니다. compileSdk 속성은 Kotlin 또는 Java 소스 코드를 컴파일할 때 사용할 Android SDK 버전을 지정합니다.

Kotlin

android {
    ...
    compileSdk = 33
}

Groovy

android {
    ...
    compileSdk 33
}

각 Android 버전은 JDK의 특정 버전과 사용 가능한 Java API의 하위 집합을 지원합니다. 지정된 minSdk에서는 사용할 수 없지만 compileSdk에서는 사용할 수 있는 Java API를 사용하는 경우 디슈가링이라는 프로세스를 통해 이전 버전의 Android에서 API를 사용할 수 있습니다. 지원되는 API는 디슈가링을 통해 사용할 수 있는 Java 11+ API를 참고하세요.

이 표를 사용하여 각 Android API에서 지원되는 Java 버전과 사용 가능한 Java API에 관한 세부정보를 찾을 수 있는 위치를 확인하세요.

Android 자바 지원되는 API 및 언어 기능
14(API 34) 17 핵심 라이브러리
13(API 33) 11 핵심 라이브러리
12(API 32) 11 Java API
11 이하 Android 버전

어떤 JDK가 Java 소스 코드를 컴파일하나요?

Java 도구 모음 JDK에는 Java 소스 코드를 컴파일하는 데 사용되는 Java 컴파일러가 포함되어 있습니다. 이 JDK는 빌드 중에 javadoc 및 단위 테스트도 실행합니다.

도구 모음은 Gradle을 실행하는 데 사용되는 JDK로 기본 설정됩니다. 기본값을 사용하고 여러 머신(예: 로컬 머신과 별도의 지속적 통합 서버)에서 빌드를 실행하는 경우 다른 JDK 버전이 사용되면 빌드 결과가 다를 수 있습니다.

더 일관된 빌드를 만들려면 Java 도구 모음 버전을 명시적으로 지정하면 됩니다. 이를 다음과 같이 지정하면 됩니다.

  • 빌드를 실행 중인 시스템에서 호환되는 JDK를 찾습니다.
    • 호환되는 JDK가 없고 도구 모음 리졸버가 정의된 경우 JDK를 다운로드합니다.
  • 소스 코드에서 호출할 수 있도록 도구 모음 Java API를 노출합니다.
  • Java 언어 버전을 사용하여 Java 소스를 컴파일합니다.
  • sourceCompatibilitytargetCompatibility의 기본값을 제공합니다.

항상 Java 도구 모음을 지정하고 지정된 JDK가 설치되어 있는지 확인하거나 빌드에 도구 모음 리졸버를 추가하는 것이 좋습니다.

소스 코드가 Java, Kotlin 또는 둘 다로 작성되었는지에 따라 도구 모음을 지정할 수 있습니다. 모듈의 build.gradle(.kts) 파일 최상위 수준에서 도구 모음을 지정합니다.

다음과 같이 Java 도구 모음 버전을 지정합니다.

Kotlin

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

Groovy

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

소스가 Kotlin, Java 또는 둘 다인 경우 작동합니다.

도구 모음 JDK 버전은 Gradle을 실행하는 데 사용되는 JDK와 동일할 수 있지만 목적은 다릅니다.

Java 소스 코드에서 사용할 수 있는 Java 언어 소스 기능은 무엇인가요?

sourceCompatibility 속성은 Java 소스 컴파일 중에 사용할 수 있는 Java 언어 기능을 결정합니다. Kotlin 소스에는 영향을 미치지 않습니다.

모듈의 build.gradle(.kts) 파일에서 다음과 같이 sourceCompatibility를 지정합니다.

Kotlin

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
    }
}

Groovy

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

지정되지 않은 경우 이 속성은 기본적으로 Java 도구 모음 버전으로 설정됩니다. Java 도구 모음을 사용하지 않는 경우 기본값은 Android Gradle 플러그인이 선택한 버전(예: Java 8 이상)입니다.

Kotlin 또는 Java 소스를 컴파일할 때 어떤 Java 바이너리 기능을 사용할 수 있나요?

targetCompatibilityjvmTarget 속성은 각각 컴파일된 Java 및 Kotlin 소스의 바이트 코드를 생성할 때 사용되는 Java 클래스 형식 버전을 결정합니다.

일부 Kotlin 기능은 상응하는 Java 기능이 추가되기 전에 존재했습니다. 초기 Kotlin 컴파일러는 이러한 Kotlin 기능을 나타내는 자체 방법을 만들어야 했습니다. 이러한 기능 중 일부는 나중에 Java에 추가되었습니다. 이후 jvmTarget 수준에서는 Kotlin 컴파일러가 Java 기능을 직접 사용할 수 있으므로 성능이 향상될 수 있습니다.

Android 버전에 따라 지원되는 Java 버전이 다릅니다. targetCompatibilityjvmTarget를 늘려 추가 Java 기능을 활용할 수 있지만, 이 경우 기능을 사용할 수 있도록 최소 Android SDK 버전도 늘려야 할 수 있습니다.

targetCompatibilitysourceCompatibility보다 크거나 같아야 합니다. 실제로는 sourceCompatibility, targetCompatibility, jvmTarget가 일반적으로 동일한 값을 사용해야 합니다. 다음과 같이 설정할 수 있습니다.

Kotlin

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

Groovy

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

지정되지 않은 경우 이러한 속성의 기본값은 Java 도구 모음 버전입니다. Java 도구 모음을 사용하지 않는 경우 기본값이 다르고 빌드 문제를 일으킬 수 있습니다. 따라서 항상 이러한 값을 명시적으로 지정하거나 자바 도구 모음을 사용하는 것이 좋습니다.