Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

Java 8 언어 기능 사용하기

Android 스튜디오 3.0 이상은 Java 7 언어 기능 일체를 모두 지원하고, Java 8 언어 기능의 경우 플랫폼 버전에 따라 각각 다르게 부분적으로 지원합니다. 이 페이지에서는 사용할 수 있는 Java 8 언어 기능, 이러한 기능을 사용할 프로젝트를 올바르게 구성하는 방법 및 발생할 수 있는 알려진 문제에 대해 설명합니다. 다음 동영상을 통해 개요를 알아보세요.

참고: Android용 앱을 개발할 때에는 Java 8 언어 기능을 사용하는 것은 선택사항입니다. 프로젝트의 소스 및 대상 호환성 값을 Java 7로 유지할 수는 있지만 JDK 8을 사용하여 컴파일해야 합니다.

Android 스튜디오는 특정 Java 8 언어 기능과 이러한 기능을 사용하는 타사 라이브러리를 사용하기 위한 내장 지원 기능을 제공합니다. 그림 1과 같이 기본 도구 모음은 javac 컴파일러의 출력에 desugar라는 바이트코드 변환을 수행하여 새로운 언어 기능을 구현합니다. 더 이상 Jack이 지원되지 않으며 기본 도구 모음에 기본 제공되는 Java 8 지원을 사용하려면 먼저 Jack을 사용 중지해야 합니다.

그림 1. desugar 바이트코드 변환을 사용하는 Java 8 언어 기능 지원

지원되는 Java 8 언어 기능을 사용하기 시작하려면 3.0.0 이상으로 Android 플러그인을 업데이트하세요. 그런 다음 Java 8 언어 기능을 사용하는 각 모듈을 대상으로 (소스 코드에서 또는 종속성을 통해) Source CompatibilityTarget Compatibility를 1.8로 업데이트하세요. 그림 2에 나온 것처럼 Project Structure 대화상자를 사용하면 됩니다(File > Project Structure 클릭).

그림 2. desugar 바이트코드 변환을 사용하는 Java 8 언어 기능 지원

대응하는 build.gradle 파일에서 직접 구성할 수도 있습니다.

android {
      ...
      // Configure only for each module that uses Java 8
      // language features (either in its source code or
      // through dependencies).
      compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
      }
      // For Kotlin projects
      kotlinOptions {
        jvmTarget = "1.8"
      }
    }
    

참고: Android 스튜디오에서 프로젝트가 Jack, Retrolambda, DexGuard 중 하나를 사용 중임을 인식하는 경우 IDE는 이러한 도구에서 제공되는 Java 8 지원을 대신 사용합니다. 하지만 기본 도구 모음으로 이전할 것을 고려해 보세요.

지원되는 Java 8 언어 기능 및 API

Android 스튜디오에서 일부 Java 8 언어 기능만 지원하지만 IDE의 향후 릴리스에 더 많은 기능이 추가될 예정입니다. 사용 중인 minSdkVersion에 따라 아래 표의 설명과 같이 특정 기능과 API를 사용할 수 있습니다.

Java 8 언어 기능 호환되는 minSdkVersion
람다 식 모두 호환됩니다. Android는 람다 식의 직렬화를 지원하지 않습니다.
메서드 참조 모두 호환됩니다.
형식 주석 모두 호환됩니다. 하지만 형식 주석 정보는 런타임이 아니라 컴파일 시간에 확인할 수 있습니다. 또한, 이 플랫폼은 API 레벨 24 이하에서 TYPE을 지원하며 ElementType.TYPE_USE 또는 ElementType.TYPE_PARAMETER는 지원하지 않습니다.
기본 및 정적 인터페이스 메서드 모두 호환됩니다.
주석 반복 모두 호환됩니다.
Java 8 언어 API 호환되는 minSdkVersion
java.lang.annotation.Repeatable API 레벨 24 이상
AnnotatedElement.getAnnotationsByType(Class) API 레벨 24 이상
java.util.stream API 레벨 24 이상
java.lang.FunctionalInterface API 레벨 24 이상
java.lang.reflect.Method.isDefault() API 레벨 24 이상
java.util.function API 레벨 24 이상

위에서 설명한 Java 8 언어 기능과 API 외에도, Android 스튜디오 3.0 이상에서는 try-with-resources 지원을 모든 Android API 레벨로 확장합니다.

Desugar는 현재 MethodHandle.invoke 또는 MethodHandle.invokeExact를 지원하지 않습니다. 소스 코드나 모듈 종속성 중 하나에서 이러한 메서드 중 하나를 사용하는 경우 minSdkVersion 26 이상을 지정해야 합니다. 그러지 않으면 다음 오류가 발생합니다.

Dex: Error converting bytecode to dex:
    Cause: signature-polymorphic method called without --min-sdk-version >= 26
    

경우에 따라 invoke 또는 invokeExact 메서드가 라이브러리 종속성에 포함되어 있을 때도 모듈에서 이러한 메서드를 사용하지 않을 수 있습니다. 따라서 이 라이브러리를 minSdkVersion 25 또는 이전 버전에서 계속 사용하려면 코드 축소를 사용 설정하여 사용되지 않는 메서드를 삭제합니다. 그래도 효과가 없으면 지원되지 않는 메서드를 사용하지 않는 다른 라이브러리를 사용해 봅니다.

기본 도구 모음으로 이전하기

Android 스튜디오에서 프로젝트가 Jack, Retrolambda, DexGuard 중 하나를 사용 중임을 인식하는 경우 IDE는 이러한 도구에서 제공되는 Java 8 지원을 대신 사용합니다. 하지만 기본 도구 모음과 비교해 볼 때, 이들 도구는 몇 가지 기능과 지원 측면에서 부족한 점이 있습니다. 따라서 이 섹션의 안내에 따라 Android 스튜디오의 기본 도구 모음으로 이전하시기 바랍니다.

Jack에서 이전하기

이번 발표에 따라 Jack 도구 모음은 지원 중단됩니다. 프로젝트에서 Jack을 사용하는 경우 Android 스튜디오의 기본 도구 모음에 내장된 Java 8 지원을 사용하도록 이전해야 합니다. 기본 도구 모음을 사용하면 Java 8 언어 기능을 사용하는 타사 라이브러리, Instant Run, 중간 .class 파일을 사용하는 도구도 지원됩니다.

Jack을 사용 중지하고 기본 도구 모음으로 전환하려면 모듈의 build.gradle 파일에서 jackOptions 블록을 삭제하기만 하면 됩니다.

android {
        ...
        defaultConfig {
            ...
            // Remove this block.
            jackOptions {
                enabled true
                ...
            }
        }

        // Keep the following configuration in order to target Java 8.
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
        // For Kotlin projects
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }
    

Retrolambda에서 이전하기

Android 스튜디오의 기본 도구 모음과 비교할 때, Retrolambda는 Java 8 언어 기능을 사용하는 타사 라이브러리를 지원하지 않습니다. 기본 도구 모음으로 이전하려면 프로젝트 수준 build.gradle 파일에서 Retrolambda 종속성을 삭제합니다.

buildscript {
      ...
       dependencies {
          // Remove the following dependency.
          classpath 'me.tatarka:gradle-retrolambda:<version_number>'
       }
    }
    

또한, 각 모듈의 build.gradle 파일에서 Retrolambda 플러그인과 retrolambda 블록을 삭제합니다.

    // Remove the following plugin.
    apply plugin: 'me.tatarka.retrolambda'
    ...
    // Remove this block after migrating useful configurations.
    retrolambda {
        ...
        // If you have arguments for the Java VM you want to keep,
        // move them to your project's gradle.properties file.
        jvmArgs '-Xmx2048m'
    }
    

Java 8 언어 기능 지원 사용 중지하기

Java 8 언어 기능 지원과 관련된 문제가 발생하는 경우 gradle.properties 파일에 다음을 추가하여 기능을 사용 중지할 수 있습니다.

android.enableDesugar=false
    

버그를 제출해 주시면 Java 8 지원을 개선하는 데 큰 도움이 될 것입니다.