16KB 페이지 크기 지원

Android 过去仅支持 4 KB 内存页面大小, 优化了系统内存性能,以针对 Android 设备通常具备的功能。从 Android 15 开始,AOSP 支持 配置为使用 16 KB (16 KB) 页面大小的设备 设备)。如果您的应用使用任何 NDK 库,请直接使用 或者通过 SDK 间接创建,那么,您需要重新构建自己的应用 支持这些 16KB 设备。

随着设备制造商不断打造出 物理内存 (RAM),许多此类设备都会采用 16KB(以及 页面大小以优化设备的性能。正在添加 支持 16 KB 页面大小的设备,可使您的应用在这些设备上运行 并有助于您的应用从相关的广告效果中获益 改进。如果不重新编译,应用可能无法在 16KB 设备上运行 在未来的 Android 版本中正式推出。

为帮助您为应用添加支持,我们提供了有关如何检查 如果您的应用受到影响 重新构建您的应用(如果适用),以及如何在 Google Play 中 使用模拟器(包括 Android 15)的 16 KB 环境 系统映像)。

이점 및 성능 향상

16KB 페이지 크기로 구성된 기기는 평균적으로 약간 더 많은 메모리를 사용하지만 시스템과 앱 모두에서 다양한 성능이 개선됩니다.

  • 시스템에 메모리 문제가 있는 동안 앱 실행 시간 단축: 평균 3.16% 감소, 테스트한 일부 앱의 경우 더 큰 개선 (최대 30%)
  • 앱 실행 중 전원 소모 감소: 평균 4.56% 감소
  • 카메라 실행 속도 향상: 평균 핫 스타트 속도가 4.48%, 콜드 스타트 속도가 6.60% 빨라짐
  • 시스템 부팅 시간 개선: 평균 8% (약 950밀리초) 개선됨

이러한 개선사항은 초기 테스트를 기반으로 하며 실제 기기의 결과는 다를 수 있습니다. 테스트를 계속하면서 앱의 잠재적 이점에 관한 추가 분석을 제공할 예정입니다.

앱이 영향을 받는지 확인하기

如果您的应用使用了任何原生代码,则应重新构建应用以支持 16 KB 设备。如果您不确定自己的应用是否使用了原生代码,可以使用 APK 分析器确定是否存在任何原生代码,然后检查您找到的任何共享库的 ELF 段对齐情况

如果您的应用仅使用以 Java 或 Kotlin 编程语言编写的代码(包括所有库或 SDK),则该应用已经支持 16 KB 设备。不过,我们建议您在 16 KB 环境中测试应用,以验证应用行为是否没有意外回归。

앱에서 네이티브 코드를 사용하는지 확인

다음 중 하나라도 해당하는 경우 앱에서 네이티브 코드를 이용하는 것입니다.

  • 앱에서 C/C++ (네이티브) 코드를 사용합니다. 앱에서 Android NDK를 사용하는 경우 앱에서 네이티브 코드를 사용합니다.
  • 앱이 이를 사용하는 서드 파티 네이티브 라이브러리 또는 종속 항목 (예: SDK)과 연결됩니다.
  • 앱이 기기에서 네이티브 라이브러리를 사용하는 서드 파티 앱 빌더로 빌드되었습니다.

APK Analyzer를 사용하여 네이티브 라이브러리 식별

APK Analyzer는 빌드된 APK의 다양한 측면을 평가할 수 있는 도구입니다. 앱에서 네이티브 코드 또는 라이브러리를 사용하는지 확인하려면 다음 단계를 따르세요.

  1. Android 스튜디오를 열고 File > Open을 클릭한 다음 프로젝트를 선택합니다.
  2. 메뉴 바에서 Build > Analyze APK...를 클릭합니다.

    APK Analyzer를 실행하는 스튜디오 빌드 메뉴 옵션

  3. 분석하려는 APK를 선택합니다.

  4. 공유 객체(.so) 파일(있는 경우)을 호스팅하는 lib 폴더 내부를 살펴봅니다. 공유 오브젝트 파일이 있으면 앱에서 네이티브 코드를 사용합니다. 공유 오브젝트 파일이 없거나 lib 폴더가 없는 경우 앱에서 네이티브 코드를 사용하지 않는 것입니다.

    공유 오브젝트 파일이 있음을 보여주는 APK Analyzer 뷰

공유 라이브러리의 ELF 세그먼트 정렬 확인

공유 라이브러리의 경우 16KB ELF 정렬을 사용하여 공유 라이브러리의 ELF 세그먼트가 올바르게 정렬되어 있는지 확인합니다. Linux 또는 macOS에서 개발하는 경우 다음 섹션에 설명된 대로 check_elf_alignment.sh 스크립트를 사용할 수 있습니다. 명령줄 도구를 직접 사용할 수도 있습니다.

check_elf_alignment.sh 스크립트 사용 (Linux 또는 macOS)

check_elf_alignment.sh 스크립트를 사용하여 ELF 세그먼트의 정렬을 확인하려면 다음 단계를 따르세요.

  1. check_elf_alignment.sh 스크립트를 파일에 저장합니다.

  2. 앱의 APK 파일에서 스크립트를 실행합니다.

    check_elf_alignment.sh APK_NAME.apk
    

    스크립트는 모든 arm64-v8a 공유 라이브러리에 대해 ALIGNED 또는 UNALIGNED를 출력합니다.

  3. arm64-v8a 또는 x86_64 공유 라이브러리가 UNALIGNED인 경우 해당 라이브러리의 패키징을 업데이트한 다음 앱을 다시 컴파일하고 이 섹션의 단계에 따라 다시 테스트해야 합니다.

명령줄 도구 직접 사용

명령줄 도구를 직접 사용하여 ELF 세그먼트의 정렬을 확인하려면 다음 단계를 따르세요.

  1. Android 스튜디오의 SDK Manager 또는 sdkmanager 명령줄 도구를 사용하여 Android SDK 빌드 도구 버전 35.0.0 이상과 Android NDK가 모두 설치되어 있는지 확인합니다.
  2. 앱의 APK 파일의 압축을 풉니다.

    Linux 또는 macOS

    unzip APK_NAME.apk -d /tmp/my_apk_out
    

    Windows (PowerShell)

    Expand-Archive -Path .\APK_NAME.apk -DestinationPath ~\tmp\my_apk_out
    
  3. APK 파일을 추출한 임시 디렉터리에서 lib 디렉터리의 콘텐츠에 공유 객체 (.so) 파일이 있는지 확인합니다. 이는 APK Analyzer를 사용하여 네이티브 라이브러리를 식별할 때 보았던 것과 동일한 공유 오브젝트 파일입니다. 각 공유 오브젝트 파일에서 다음 명령어를 실행합니다.

    Linux 또는 macOS

    SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump -p SHARED_OBJECT_FILE.so | grep LOAD
    

    Windows (PowerShell)

    SDK_ROOT_LOCATION\Android\sdk\ndk\NDK_VERSION\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-objdump.exe -p SHARED_OBJECT_FILE.so | Select-String -Pattern "LOAD"
    

    여기서 SDK_ROOT_LOCATION는 Android SDK를 설치한 디렉터리의 경로이고, SHARED_OBJECT_FILE는 확인 중인 공유 객체 파일의 이름이며, NDK_VERSION는 설치된 Android NDK 버전입니다 (예: 28.0.12433566). 확인하는 각 파일의 출력은 다음과 같습니다.

    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**14
    LOAD off    0x0000000000042a90 vaddr 0x0000000000043a90 paddr 0x0000000000043a90 align 2**14
    LOAD off    0x0000000000046230 vaddr 0x0000000000048230 paddr 0x0000000000048230 align 2**14
    
  4. 출력 줄을 확인하여 부하 세그먼트의 값이 2**14보다 작지 않은지 확인합니다. 로드 세그먼트가 2**13, 2**12 이하 값인 경우 해당 라이브러리의 패키징을 업데이트한 다음 앱을 다시 컴파일하고 이 섹션의 단계에 따라 다시 테스트해야 합니다.

  5. 그런 다음 앱의 APK 파일에서 zipalign 명령줄 도구를 실행합니다.

    Linux 또는 macOS

    SDK_ROOT_LOCATION/Android/sdk/build-tools/35.0.0/zipalign -v -c -P 16 4 APK_NAME.apk
    

    Windows (PowerShell)

    SDK_ROOT_LOCATION\Android\sdk\build-tools\35.0.0\zipalign.exe -v -c -P 16 4 APK_NAME.apk
    

    여기서 SDK_ROOT_LOCATION는 Android SDK를 설치한 디렉터리의 경로이고 APK_NAME는 앱의 APK 파일 이름입니다. 모든 공유 라이브러리가 올바르게 정렬되면 출력의 마지막 줄에 'Verification successful'이라고 표시됩니다.

    인증에 실패한 경우 일부 공유 라이브러리를 다시 정렬해야 하므로 해당 라이브러리의 패키징을 업데이트한 다음 앱을 다시 컴파일하고 이 섹션의 단계에 따라 다시 테스트해야 합니다.

16KB 기기 지원으로 앱 빌드

16KB 기기를 지원하려면 네이티브 코드를 사용하는 앱이 다음 섹션에 설명된 단계를 완료해야 합니다. AGP 버전 8.5.1 이상 및 NDK 버전 r28 이상으로 업데이트하고 16KB 호환 사전 빌드된 종속 항목을 사용하는 경우 앱은 기본적으로 16KB 호환됩니다.

공유 라이브러리의 패키징 업데이트

AGP 버전 8.5.1 이상으로 업그레이드하고 압축되지 않은 공유 라이브러리를 사용하는 것이 좋습니다.

AGP 버전 8.5.1 이상

16KB 기기의 경우 비압축 공유 라이브러리와 함께 제공되는 앱이 16KB zip 정렬 경계에서 정렬되어야 합니다. 이렇게 하려면 Android Gradle 플러그인 (AGP) 버전 8.5.1 이상으로 업그레이드해야 합니다. 업그레이드 절차에 관한 자세한 내용은 Android Gradle 플러그인 업그레이드 어시스턴트 섹션을 참고하세요.

AGP 버전 8.5 이하

AGP를 버전 8.5.1 이상으로 업그레이드할 수 없는 경우 압축된 공유 라이브러리를 사용하도록 전환하는 것이 좋습니다. 정렬되지 않은 공유 라이브러리로 인한 앱 설치 문제를 방지하려면 앱을 패키징할 때 Gradle이 공유 라이브러리를 압축하도록 Gradle 구성을 업데이트합니다.

Groovy

build.gradle 파일에 다음 옵션을 추가합니다.

android {
  ...
  packagingOptions {
      jniLibs {
        useLegacyPackaging true
      }
  }
}

Kotlin

build.gradle.kts 파일에 다음 옵션을 추가합니다.

android {
  ...
  packagingOptions {
      jniLibs {
        useLegacyPackaging = true
      }
  }
}

16KB ELF 정렬을 사용하여 앱 컴파일

16KB 기기에서 앱을 실행하려면 공유 라이브러리의 ELF 세그먼트가 16KB ELF 정렬을 사용하여 올바르게 정렬되어야 합니다.

16KB ELF 정렬을 사용하여 앱을 컴파일하려면 사용 중인 Android NDK 버전에 따라 다음 섹션 중 하나의 단계를 완료합니다.

Android NDK r28 이상

NDK 버전 r28 이상은 기본적으로 16KB 정렬로 컴파일합니다.

Android NDK r27

Android NDK 버전 r27 이상으로 16KB 정렬 공유 라이브러리 컴파일을 지원하려면 다음과 같이 ndk-build, build.gradle, build.gradle.kts 또는 링커 플래그를 업데이트해야 합니다.

ndk-build

Application.mk에서:

APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true

Groovy

build.gradle 파일에서 인수 -DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON를 설정합니다.

android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake or ndk-build script.
    externalNativeBuild {
      // For ndk-build, instead use the ndkBuild block.
      cmake {
        // Passes optional arguments to CMake.
        arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
      }
    }
  }
}

Kotlin

build.gradle.kts 파일에서 인수 -DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON를 설정합니다.

android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake or ndk-build script.
    externalNativeBuild {
      // For ndk-build, instead use the ndkBuild block.
      cmake {
        // Passes optional arguments to CMake.
        arguments += listOf("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON")
      }
    }
  }
}

기타 빌드 시스템

다음 링커 플래그를 지정합니다.

-Wl,-z,max-page-size=16384

Android NDK r26 이하

Android NDK 버전 r26 이하로 16KB 정렬 공유 라이브러리 컴파일을 지원하려면 다음과 같이 ndk-build 또는 cmake 구성을 업데이트해야 합니다.

ndk-build

16KB ELF 정렬을 사용 설정하도록 Android.mk를 업데이트합니다.

LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384"

CMake

16KB ELF 정렬을 사용 설정하도록 CMakeLists.txt를 업데이트합니다.

target_link_options(${CMAKE_PROJECT_NAME} PRIVATE "-Wl,-z,max-page-size=16384")

특정 페이지 크기를 참조하는 코드 인스턴스 확인

앱이 16KB 정렬이더라도 코드의 특정 위치에서 기기가 특정 페이지 크기를 사용한다고 가정하면 앱에 오류가 발생할 수 있습니다. 이를 방지하려면 다음 단계를 완료하세요.

  1. 코드 로직에서 기기의 페이지 크기가 4KB (4096)라고 가정하는 PAGE_SIZE 상수 또는 인스턴스를 참조하는 하드코딩된 종속 항목을 모두 삭제합니다.

    대신 getpagesize() 또는 sysconf(_SC_PAGESIZE)를 사용하세요.

  2. 페이지 정렬된 인수가 필요한 mmap() 및 기타 API의 사용을 찾아 필요한 경우 대안으로 대체합니다.

경우에 따라 앱에서 PAGE_SIZE를 기본 페이지 크기에 연결되지 않은 편리한 값으로 사용하는 경우 16KB 모드에서 사용할 때 앱이 중단되지 않을 수 있습니다. 그러나 이 값이 MAP_FIXED 없이 mmap와 함께 커널에 전달되면 커널은 여전히 전체 페이지를 사용하기 때문에 메모리가 낭비됩니다. 이러한 이유로 NDK r27 이상에서 16KB 모드가 사용 설정되면 PAGE_SIZE가 정의되지 않습니다.

앱이 이와 같이 PAGE_SIZE를 사용하고 이 값을 커널에 직접 전달하지 않는 경우 PAGE_SIZE를 사용하는 대신 다른 목적으로 사용되고 실제 메모리 페이지를 반영하지 않는다는 것을 반영하는 새 이름으로 새 변수를 만듭니다.

SDK의 16KB 지원 여부 확인

특히 직접 빌드하거나 최신 사전 빌드를 가져오는 경우 많은 SDK가 16KB 페이지 크기와 호환됩니다. 그러나 일부 SDK 사전 빌드 또는 SDK 버전은 16KB와 호환되지 않으므로 각 SDK 제공업체의 웹사이트를 확인하여 16KB와 함께 사용할 버전을 결정해야 합니다.

16KB 환경에서 앱 테스트

16KB 기기 지원으로 앱을 빌드한 후에는 16KB 환경에서 앱을 테스트하여 앱에 회귀가 발생하는지 확인해야 합니다. 이를 위해서는 다음 단계를 따르세요.

  1. Android 15 SDK 설정

  2. 다음 테스트 환경 중 하나를 설정합니다.

  3. 테스트 기기를 시작한 다음 다음 명령어를 실행하여 16KB 환경을 사용하고 있는지 확인합니다.

    adb shell getconf PAGE_SIZE
    

    이 명령어는 16384 값을 반환해야 합니다.

  4. 다음 zipalign 명령어를 실행하여 앱이 16KB 정렬인지 확인합니다. 여기서 APK_NAME은 앱의 APK 파일 이름입니다.

    zipalign -c -P 16 -v 4 APK_NAME.apk
    
  5. 특정 페이지 크기를 참조하는 코드 인스턴스를 변경하는 영향을 받을 수 있는 영역에 중점을 두고 앱을 철저히 테스트합니다.

16KB 기반 Android 15 시스템 이미지로 Android Emulator 설정

Android Emulator를 사용하여 16KB 환경을 설정하려면 다음 단계를 따르세요.

  1. 16KB 기반 Android 15 에뮬레이터 시스템 이미지는 Android 스튜디오 Jellyfish | 2023.3.1 및 이후 버전과 호환됩니다. 하지만 Android 15 베타를 사용할 때 최상의 환경을 이용하려면 Android 스튜디오의 최신 미리보기 버전을 다운로드하세요.

    여러 버전을 함께 설치할 수 있으므로 이미 설치되어 있는 기존 버전의 Android 스튜디오를 그대로 유지할 수 있습니다.

  2. Android 스튜디오에서 Tools > SDK Manager를 클릭합니다.

  3. SDK Platforms 탭에서 Show Package Details를 선택한 다음 Android VanillaIceCream Preview 섹션을 펼치고 만들려는 가상 기기에 따라 다음 에뮬레이터 시스템 이미지 중 하나 또는 둘 다를 선택합니다.

    • Google API 실험용 16KB 페이지 크기 ARM 64 v8a 시스템 이미지
    • Google APIs 실험용 16k 페이지 크기 Intel x86_64 Atom 시스템 이미지

    Android 스튜디오의 SDK Manager를 사용하여 16KB 에뮬레이터 시스템 이미지 다운로드

  4. 적용 > 확인을 클릭하여 선택한 시스템 이미지를 다운로드합니다.

  5. Android 15용 가상 기기를 설정하는 단계를 따르고 시스템 이미지를 선택하라는 메시지가 표시되면 다운로드한 16KB 시스템 이미지를 선택합니다. 자동으로 권장되지 않는 경우 기타 이미지 탭에서 16KB 시스템 이미지를 찾을 수 있습니다.

    기타 이미지 탭에서 16KB 에뮬레이터 이미지를 찾습니다.

  1. 장치 관리자에서 16KB 이미지 옆에 있는 점 3개를 클릭한 다음 디스크에 표시를 클릭합니다.
  2. 이 폴더에서 config.ini 파일을 찾습니다.
  3. 다음 줄을 config.ini 파일에 추가하고 변경사항을 저장합니다.

    kernel.parameters = androidboot.page_shift=14
    
  4. 변경사항을 확인하려면 다음 명령어를 실행합니다. 그러면 16384이 반환됩니다.

    adb shell getconf PAGE_SIZE
    

개발자 옵션을 사용하여 기기에서 16KB 모드 사용 설정

16KB 페이지 크기로 부팅 개발자 옵션을 전환하여 기기를 16KB 모드로 부팅합니다.

Android 15 QPR1부터 특정 기기에서 제공되는 개발자 옵션을 사용하여 기기를 16KB 모드로 부팅하고 기기 내 테스트를 실행할 수 있습니다.

이 개발자 옵션은 다음 기기에서 사용할 수 있습니다.

  • Pixel 8 및 8 Pro (Android 15 QPR1 이상)
  • Pixel 8a (Android 15 QPR1 이상)