从历史上看,Android 仅支持 4 KB 内存页面大小,这优化了系统内存性能,以适应 Android 设备通常拥有的平均总内存量。从 Android 15 开始,AOSP 支持配置为使用 16 KB 页面大小的设备(16 KB 设备)。如果您的应用直接或通过 SDK 间接使用任何 NDK 库,则需要重新构建应用,才能在这些 16 KB 设备上运行。
随着设备制造商不断制造出具有更大物理内存 (RAM) 的设备,许多此类设备将采用 16 KB(最终甚至更大)的页面大小来优化设备性能。添加对 16 KB 页面大小设备的支持,可让您的应用在这些设备上运行,并帮助您的应用受益于相关的性能改进。如果不重新编译,应用将无法在未来 Android 版本的 16 KB 设备上运行。
为帮助您为应用添加支持,我们提供了相关指南,介绍了如何检查应用是否受到影响、如何重新构建应用(如果适用),以及如何使用模拟器(包括 Android 模拟器的 Android 15 系统映像)在 16 KB 环境中测试应用。
优势和性能提升
Devices configured with 16 KB page sizes use slightly more memory on average, but also gain various performance improvements for both the system and apps:
- Lower app launch times while the system is under memory pressure: 3.16% lower on average, with more significant improvements (up to 30%) for some apps that we tested
- Reduced power draw during app launch: 4.56% reduction on average
- Faster camera launch: 4.48% faster hot starts on average, and 6.60% faster cold starts on average
- Improved system boot time: improved by 8% (approximately 950 milliseconds) on average
These improvements are based on our initial testing, and results on actual devices will likely differ. We'll provide additional analysis of potential gains for apps as we continue our testing.
检查您的应用是否受到影响
如果您的应用使用了任何原生代码,则应重新构建应用,使其支持 16 KB 设备。如果您不确定自己的应用是否使用了原生代码,可以使用 APK 分析器来确定是否存在任何原生代码,然后检查您找到的任何共享库的 ELF 段对齐情况。Android Studio 还提供了一些功能,可帮助您自动检测对齐问题。
如果您的应用仅使用以 Java 或 Kotlin 编程语言编写的代码(包括所有库或 SDK),则该应用已支持 16 KB 设备。不过,我们建议您在 16 KB 环境中测试应用,以验证应用行为是否出现意外的回归。
您的应用是否使用了原生代码?
如果您的应用符合以下任一情况,则表明其使用了原生代码:
- 您的应用使用了任何 C/C++(原生)代码。如果您的应用使用了 Android NDK,则表明其使用了原生代码。
- 您的应用与任何第三方原生库或使用这些库的依赖项(例如 SDK)关联。
- 您的应用通过使用设备上的原生库的第三方应用构建程序构建而成。
使用 APK 分析器识别原生库
APK 分析器是一款可用于对所构建的 APK 进行各方面评估的工具。如需检查您的应用是否使用了原生代码(无论是否兼容 16 KB),请执行以下操作:
- 打开 Android Studio,然后依次点击 File > Open 并选择任意项目。
从菜单栏中依次点击 Build > Analyze APK…
选择要分析的 APK。
在
lib文件夹中查找共享对象 (.so) 文件(如果有)。如果有任何共享对象文件,则表明您的应用使用了原生代码。“Alignment”(对齐方式)列会针对存在对齐问题的任何文件显示警告消息。 如果没有共享对象文件或没有lib文件夹,则表明您的应用未使用原生代码。
通过自动检查检测对齐问题
如果您的预构建库或 APK 不符合 16 KB 要求,Android Studio 会主动向您发出警告。您可以使用 APK 分析器 工具查看哪些库需要 更新,或者是否需要进行任何代码更改。
Android Studio 中的 Lint 还会突出显示未与 16 KB 对齐的原生库。
检查共享库的 ELF 段的对齐方式
对于任何共享库,请使用 16 KB ELF 对齐方式验证共享库的 ELF 段是否已正确对齐。如果您是在 Linux 或 macOS 上进行开发,则可以使用下一部分中所述的 check_elf_alignment.sh 脚本。您也可以直接使用命令行工具。
使用 check_elf_alignment.sh 脚本(Linux 或 macOS)
请按照以下步骤使用 check_elf_alignment.sh 脚本检查 ELF 段的对齐方式:
将
check_elf_alignment.sh脚本保存到文件中。对应用的 APK 文件运行该脚本:
check_elf_alignment.sh APK_NAME.apk该脚本会针对所有
arm64-v8a共享库输出ALIGNED或UNALIGNED。如果有任何
arm64-v8a或x86_64共享库为UNALIGNED,您需要 更新这些库的打包,然后 重新编译应用 并按照本部分中的步骤重新测试。
直接使用命令行工具
请按照以下步骤直接使用命令行工具检查 ELF 段的对齐方式:
- 确保已使用 Android Studio 中的 SDK 管理器 或
sdkmanager命令行工具安装 Android SDK Build-Tools 35.0.0 或更高版本以及 Android NDK。 提取应用的 APK 文件:
Linux 或 macOS
unzip APK_NAME.apk -d /tmp/my_apk_outWindows (PowerShell)
Expand-Archive -Path .\APK_NAME.apk -DestinationPath ~\tmp\my_apk_out在您提取 APK 文件的临时目录中,检查
lib目录的内容,查看是否有共享对象 (.so) 文件。这些是 您在使用 APK 分析器识别原生库时看到的相同共享对象文件。对每个共享对象文件运行以下命令: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 LOADWindows (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检查输出行,确保加载段的值不小于
2**14。如果有任何加载段的值为2**13、2**12或更低 ,您需要更新这些库的打包,然后 重新编译应用并按照本部分中的步骤重新测试。接下来,对应用的 APK 文件运行
zipalign命令行工具:Linux 或 macOS
SDK_ROOT_LOCATION/Android/sdk/build-tools/35.0.0/zipalign -v -c -P 16 4 APK_NAME.apkWindows (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”(验证成功)。
构建支持 16 KB 设备的应用
如果您的应用使用了原生代码,请完成以下部分中列出的步骤,确保您的应用支持 16 KB 设备:
更新共享库的打包
升级到 AGP 8.5.1 或更高版本,并使用未压缩的共享库。
使用 bundletool 验证 ZIP 对齐方式
如需查看 bundle 的对齐方式,请使用:
bundletool dump config --bundle=<my .aab> | grep alignment
如果您看到 PAGE_ALIGNMENT_16K,则表示您的 bundle 请求 16 KB ZIP 对齐方式。如果您看到 PAGE_ALIGNMENT_4K,则表示从该 AAB 构建的 APK 在 ZIP 文件中包含 4 KB 对齐的 .so 文件。
AGP 8.5.1 或更高版本
16 KB 设备要求随附未压缩共享库的应用在 16 KB 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
}
}
}
AGP 8.0 或更低版本
如果您使用的 AGP 版本为 8.0 或更低版本,还需要在 gradle.properties 文件中为 App Bundle 停用未压缩的原生库选项:
android.bundle.enableUncompressedNativeLibs=false
使用 16 KB ELF 对齐方式编译应用
16 KB 设备要求共享库的 ELF 段使用 16 KB ELF 对齐方式正确对齐,应用才能运行。
对于游戏开发者,如果您的游戏在 Unity 游戏引擎之上运行,请参阅 Unity 指南。如果您的游戏在 Unreal 游戏引擎 之上运行, 请参阅 Unreal 指南。对于原生游戏引擎,请继续阅读本指南。
如需使用 16 KB ELF 对齐方式编译应用,请根据您使用的 Android NDK 版本完成以下某个部分中的步骤。
Android NDK r28 及更高版本
NDK r28 及更高版本默认编译与 16 KB 对齐的库。
Android NDK r27
如需支持使用 Android NDK
r27 及更高版本编译与 16 KB 对齐的共享库,您需要按如下方式更新 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 及更低版本
请务必更新 NDK。只有在万不得已的情况下才应使用此方法,并且不保证提供支持。
如需支持使用 Android NDK r26 或更低版本编译与 16 KB 对齐的共享库,您需要按如下方式更新 ndk-build 或 cmake 配置:
ndk-build
更新 Android.mk 以启用 16 KB ELF 对齐方式:
LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384"
CMake
更新 CMakeLists.txt 以启用 16 KB ELF 对齐方式:
target_link_options(${CMAKE_PROJECT_NAME} PRIVATE "-Wl,-z,max-page-size=16384")
Android NDK r22 及更低版本不兼容
请务必更新 NDK。只有在万不得已的情况下才应使用此方法,并且不保证提供支持。
除了 NDK r26 及更低版本的步骤之外,common-page-size=16384 还可以
解决旧版 GNU ld 和 LLVM lld 链接器中的 bug。只有当 ELF 中也存在 .relro_padding 部分时,此方法才有效。这取决于链接器的版本和编写的具体程序。这些 NDK 版本不受支持,如果此方法不起作用,请先更新 NDK 版本,然后再报告任何问题。
修复代码并解决运行时问题
即使您的应用与 16 KB 对齐,如果代码中的某些位置假定设备使用特定页面大小,您的应用也可能会遇到错误。为避免这种情况,请完成以下步骤:
移除代码逻辑中引用
PAGE_SIZE常量或假定设备的页面 大小为 4 KB (4096) 的实例的任何硬编码依赖项。查找
mmap()和其他需要页面对齐 实参的 API 的用法,并在必要时替换为替代方案。
在某些情况下,如果您的应用将 PAGE_SIZE 用作与底层页面大小无关的便捷值,则在 16 KB 模式下使用时,不会导致应用崩溃。但是,如果此值通过 mmap 传递给内核,而没有 MAP_FIXED,内核仍会使用整个页面,从而浪费一些内存。因此,在 NDK r27 及更高版本上启用 16 KB 模式时,PAGE_SIZE 未定义。
如果您的应用以这种方式使用 PAGE_SIZE,并且从不直接将此值传递给内核,则可以创建一个具有新名称的新变量,而不是使用 PAGE_SIZE,以反映该变量用于其他用途,并且不反映实际的内存页面。
检查 SDK 是否支持 16 KB
许多 SDK 都兼容 16 KB 的页面大小,尤其是当您自行构建这些 SDK 或获取最新的预构建版本时。但是,由于某些 SDK 预构建版本或 SDK 版本不兼容 16 KB,因此您应查看每个 SDK 提供方的网站,以确定要与 16 KB 搭配使用的版本。
在 16 KB 环境中测试应用
构建支持 16 KB 设备的应用后,您需要在 16 KB 环境中测试应用,以查看应用是否出现任何回归问题。为此,请按以下步骤操作:
设置 Android 15 SDK 或更高版本。
设置以下某个测试环境:
启动测试设备,然后运行以下命令以验证其是否使用 16 KB 环境:
adb shell getconf PAGE_SIZE该命令应返回
16384值。运行以下
zipalign命令以验证您的应用是否与 16 KB 对齐,其中 APK_NAME 是 应用的 APK 文件的名称:zipalign -c -P 16 -v 4 APK_NAME.apk全面测试您的应用,重点关注可能受到 更改引用特定页面大小的代码实例影响的任何区域。
使用基于 16 KB 的系统映像设置 Android 模拟器
如需使用 Android 模拟器设置 16 KB 环境,请按照以下步骤操作:
- 在 Android Studio 中,依次点击 Tools > SDK 管理器 。
在 SDK Platforms 标签页中,勾选 Show Package Details,然后展开 Android VanillaIceCream 或更高版本部分,并根据要创建的虚拟设备选择以下一个或两个 模拟器系统映像:
- Google APIs Experimental 16 KB Page Size ARM 64 v8a System Image
- Google APIs Experimental 16 KB Page Size Intel x86_64 Atom System Image
点击 Apply > OK ,下载您选择的任何系统映像。
按照步骤为 Android 15 设置虚拟设备,并在 系统提示您选择系统映像时,选择您下载的 16 KB 系统映像。如果系统未自动推荐,您可以在 Other Images 标签页中找到 16 KB 系统映像。
启动模拟器
完成 Android 模拟器和虚拟设备的设置后,从目标设备菜单或命令行启动 模拟器 。
使用开发者选项在设备上启用 16 KB 模式
切换以 16KB 页面大小启动设备开发者选项,以在 16 KB 模式下启动设备。
在 Android 15 的 QPR 版本中,您可以使用某些设备上提供的开发者选项,以 16 KB 模式启动设备并执行设备端测试。在使用开发者选项之前,请依次前往设置 > 系统 > 软件更新,并应用所有可用的更新。
此开发者选项适用于以下设备:
Pixel 8 和 Pixel 8 Pro(搭载 Android 15 QPR1 或更高版本)
Pixel 8a(搭载 Android 15 QPR1 或更高版本)
Pixel 9、9 Pro 和 9 Pro XL(搭载 Android 15 QPR2 或更高版本)
Pixel 9a(搭载 Android 16 或更高版本)
16 KB 向后兼容模式
页面大小兼容模式下的警告
当设备运行 16 KB 内核时,16 KB 向后兼容选项可用。当满足以下条件时,软件包管理系统会以 16 KB 向后兼容模式运行应用:
- 如果应用具有 4 KB LOAD 段对齐的 ELF 文件(扩展名为
.so)。 - 如果压缩后的 APK 包含 4 KB ZIP 对齐的未压缩 ELF 文件。
如果软件包管理系统为某应用启用了 16 KB 向后兼容模式,该应用在首次启动时会显示一条警告,表明它正以 16 KB 向后兼容模式运行。
16 KB 向后兼容模式可让部分应用正常运行,但为了实现最佳可靠性和稳定性,应用仍应以 16 KB 对齐。
在应用信息页面上的高级下,调整以 页面大小兼容模式运行应用这项设置的切换开关,为特定应用启用或停用 16 KB 向后兼容模式 。仅当设备以 16 KB 页面大小时,这项设置才会显示。
页面大小兼容模式设置
如需强制为设备上的每个应用启用 16 KB 向后兼容,请执行以下操作:
adb shell setprop bionic.linker.16kb.app_compat.enabled true
adb shell setprop pm.16kb.app_compat.disabled false
如需强制为设备上的每个应用停用 16 KB 向后兼容,请执行以下操作:
adb shell setprop bionic.linker.16kb.app_compat.enabled false
adb shell setprop pm.16kb.app_compat.disabled true
在 Android 17 中,您还可以强制为每个应用停用 16 KB 向后兼容,并导致任何不兼容的二进制文件立即中止:
adb shell setprop bionic.linker.16kb.app_compat.enabled fatal
adb shell setprop pm.16kb.app_compat.disabled true
将 android:pageSizeCompat 属性设置为启用或停用,以在特定应用的 AndroidManifest.xml 中启用或停用向后兼容模式。设定此属性后,该应用在启动时不会显示向后兼容模式警告。
Google Play 兼容性要求
随着设备制造商为设备配备更多 RAM 以优化性能,许多设备将采用更大的页面大小(例如 16 KB)。为了迎接这些即将推出的设备,Google Play 将推出新的兼容性要求:自 2025 年 11 月 1 日起,所有提交到 Google Play 且以搭载 Android 15(API 级别 35)及更高版本的设备为目标平台的新应用和现有应用更新都必须支持 16 KB 的页面大小。
如需详细了解此兼容性要求,请参阅这篇博文。