likes
comments
collection
share

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

作者站长头像
站长
· 阅读数 37

其实这应该是适配 「Android 15 上 16K Page Size 」相关内容的第三篇,为什么会有第三篇呢?还是因为前两篇之后,有些人还是觉得,对于如何适配这件事不是很理解,刚好上一篇讲解「快速适配 16K Page Size」 的时候,就留下了一个“玄学”的问题,那么本篇就用具体的例子来进行「填坑」,算是对于 16K Page Size 这个话题的收尾。

适配

这里再再再简单介绍下,正常的适配思路应该是:

  • 确定 so 是否 16K 对齐,可以通过前两篇文章里的脚本或者 readelf 工具进行判断,例如 readelf 的到 4000(16384),就认为对齐。
  • 代码是否在 mmap / sysconf 写死了 4096(0x1000)

当然,并不是所有写死 4096(0x1000) 的地方就有问题,就算是 mmap ,也只是要求 offset 对齐:offset must be a multiple of the page size as returned by sysconf(_SC_PAGE_SIZE)

 	void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

强调这个,是因为最近真的有人问我,为什么我改了 xxx 4096 ,但是没效果

具体场景具体区分,在代码不存在问题后,就可以修改编译配置,如:

  • NDK r27 之前,Android.mk 增加 LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384
  • NDK r27 开始,Application.mk 配置 APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true

如果是 CMakeLists.txt ,则:

  • 3.13 之前: target_link_libraries(a4ijkplayer "-Wl,-z,max-page-size=16384")

  • 3.13 之后:target_link_options(a4ijkplayer PRIVATE "-Wl,-z,max-page-size=16384")

基本上正常适配就是这么简单,在有源码的前提下,重新编译后就可以正常运行到 16K Page Size 的机器。

而今天后面要讲的,则是不正常的情况,就是你按照上面的调整之后,依然会有 SIGNAL Crash 的填坑思路,大多都是因为「陈年的代码,上古的工具链,复杂的引用」所造成的问题。

问题

本次就用 IJKPlayer 的适配编译作为例子,为什么用 IJKPlayer 做例子?因为它的链路够复杂,有源码,「代码够老」,需求也够大

首先你肯定是需要一个能跑起来的环境,这也是适配 16K Page Size 的基础:

  • 有源码
  • 能支持编译的环境

默认 IJKPlayer 推荐使用 android-ndk-r10e ,关于环境配置的问题这里就不多赘述,毕竟这不是本篇的重点,需要的可以看:

github.com/CarGuo/GSYV…

对于使用 android-ndk-r10e 编译,并且不做「任何适配」的 arm64 so 库,我们直接把 ijkplayer 运行到 16K Page Size 的模拟器,你大致会看到类似如下所示的 crash :

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

可能有人就发现,这个并不是一个典型的不对齐报错,一般情况下的 16K 不对齐报错,应该是类似下方这种提示:

java.lang.UnsatisfiedLinkError: dlopen failed: empty/missing DT_HASH ···· (new hash type from the future?)

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

那么我们通过 readelf 工具,对刚刚出错的 libijksdl.so 进行简单分析,可以看到两个 LOAD 段的 Align 是 10000(65536) ,也就是 64K 对齐,属于 16K 的 4倍,那「理论上」应该是对齐的,所以前面 crash 的时候,并没有提示 so 不对齐,而是在某段代码执行时出现 crash。

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

如果我们通过 ./aarch64-linux-android-addr2line -f -e 去看出现问题的方法和位置,大概就会看到出现异常的地方会是 g_jvm = vm 这段,这时候就会出现让人「懵圈」的情况,为什么这样的赋值会导致 SIGNAL 11 code2 的异常?

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

接着你可能会怀疑是不是 static 的问题,如果你将代码里的所有 static 声明去除,也许就会看到出错的位置变了,但是还是和「静态变量」或者「全局声明」有关系,然后你继续改,它继续换位置错,最后甚至报错可能会去到 ndk 的源码层,然后你又会陷入停滞。

也许这时候,你开始怀疑对齐是不是有问题,然后 ./aarch64-linux-android-readelf -SW 去看 Section 的时候,就会发现 .bss 和 .data 的分配又貌似没问题,然后继续陷入僵局。

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

事实上,在这个排查问题,我们不应该被报错地址带偏,首先 GCC 本身的警告和错误的指向就不一定靠谱,而且在这目前这个情况下,它不支持表达性诊断 ,所以我们应该回到正确的思路上,通过 ./aarch64-linux-android-strings -a 我们也确定了用之前我们的 NDK r10e 编译时使用的是 GCC 这一点 。

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

我们按照正确的逻辑思考,首先动态库在 4K Page Size 下正常运行,然后在 16K Page Size 下出现 SIGNAL 11 code2 的寻址异常,并且代码里没有 mmapsysconf 等写死 4096(0x1000) 的地方,那么问题肯定是出现在编译工具链路上

毕竟 NDK r10e 已经是 2015 年的产物,所以我们有理由怀疑,这里编译的 10000 其实并不是真的 64K 对齐,因为:

虽然 AArch64 编译器默认生成 ELF 文件部分与 64K 对齐,从而兼容所有 AArch64 机器,但如果工具出现 bug ,例如旧版本 patchelf 操作的二进制文件,或自定义编译器标志不对,就可能会导致某些二进制的部分仅与 4K 对齐。

升级 NDK

我们这里先选择将 NDK 工具升级到 r21 版本,至于为什么先选 r21,大致还是因为越后面的升级成本越高,具体后面我们会介绍,后面会列出不同版本的升级概述,这里我们先看 r21 版本编译后的编译情况。

想通过 r21 编译,对于 IJKPlayer ,理论上你会遇到以下问题:

  • tools/do-detect-env.sh 文件下增加你想支持的 ndk 版本: 11*|12*|13*|14*|15*|16*|21*|22*|25*|26*|27*)

  • Bad file descriptor error: invalid argument '-std=c99 :此时你需要在所有 Android.mk 下将所有的 LOCAL_CFLAGS += -std=c99 去掉,因为 GCC 早在 r18 就被移除了

  • Invalid NDK_TOOLCHAIN_VERSION value: 4.9 :同样是因为 GCC 已经移除,所以需要将 Application.mk 下的 NDK_TOOLCHAIN_VERSION=4.9 移除

  • APP_STL := stlport_static is not supported :同样在 r18 的时候,stlport 也已经被移除,所以我们需要将 Application.mk 下的 APP_STL 修改为 APP_STL := c++_static ,采用 libc++ 实现

  • 从 r21开始 ndk-bundle/build/tools/make-standalone-toolchain.sh 中会调用 ndk-bundlel/build/tools/make-standalone-toolchain.py ,所以需要把 tools/do-compile-ffmpeg.sh 下对应的 FF_ANDROID_PLATFORM 修改为 FF_ANDROID_PLATFORM=android-21 ,同理还是有 tools/do-compile-openssl.sh

基本上修改完成后,就可以使用 NDK 打包,之后我们通过 readelf 再看打包出来的 so ,可以看到此时 Align 是 1000(4096) ,因为我们此时还没有做适配调整,所以打出来的 so 都是 4K对齐

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

如果此时我们在 16K 模拟器上直接运行 so ,就可以看到类似 empty/missing DT_HASH 这样的不对齐报错了,所以接下来我们可以开始修改编译配置,让 so 支持 16K 对齐:

ijkmedia/ijkj4a/Android.mk

ijkmedia/ijkplayer/Android.mk

ijkmedia/ijksdl/Android.mk

ijkmedia/ijkyuv/Android.mk

ijkmedia/ijksoundtouch/Android.mk

ijkmedia/ijksoundtouch/source/Android-lib/jni/Android.mk

ijkmedia/ijksoundtouch/source/Android-lib/jni/Application.mk

ijkprof/android-ndk-profiler-dummy/jni/Android.mk

需要修改的文件具体为上面的位置,大概修改就是类似如下所示,主要是添加 LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

另外,还需要在 tools/do-compile-ffmpeg.sh tools/do-compile-openssl.sh 下添加FF_EXTRA_LDFLAGS="-W1,-z,max-page-size=16384" 来让 ffmpeg 也构建为 16K :

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

修改后重新构建 so,此时我们用 readelf 再看打包出来的 so ,嗯,可以看到 Align 是 4000(16384) ,也就是 16K 对齐的状态了。

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

但是当我们再将项目运行到 16K 模拟器时,发现项目还是依旧 crash ,虽然报错的地址和位置变了,但是依然还是和「静态变量」还有「全局变量」有关系,这就让人很无奈了,难道真的只能升级到 r27?

但是升级 r27 的成本无疑难以接受,所以接着我们继续尝试升级到 r22

升级到 r22 ,你可能会遇到类似如下的提示错误提示,那么你可以添加 -WI,-Bsymbolic 来解决问题:

ld: error: relocation R_AARCH64_ADR_PREL_PG_HI21 cannot be used against symbol ff_cos_32; recompile with -fPIC

至于为什么,其中 -Wl,-Bsymbolic Wl 表示将紧跟其后的参数,传递给连接器 ld,而 Bsymbolic 表示强制采用本地的全局变量定义,这样就不会出现类似「全局变量被同名定义给覆盖」的问题,理论上 -Bsymbolic 与 - pie 比较接近。

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

至于为什么我会找到这个 fix ,其实是在 ExoPlayer 支持 extension 编译 ffmpeg 的 issue 看到: github.com/google/ExoP…

此时再重新打包所有 so ,再运行到 16K 模拟器,发现终于可以正常播放视频了,我们再看 r22 下的,已经是 clang 11.0.5 的版本。

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

那么 r22 对比 r21 又有什么变化呢?为什么 r22 构建之后的包就可以正常适配 16K

我们看 r22 的更新说明,有几个关键变动:

  • GNU binutils 已弃用,将在即将发布的 NDK 版本中被删除,包括 GNU assembler (as) ,如果使用 as 请转为 clang
  • LLD 现在是默认链接器
  • libc++ 升级
  • llvm-ar 代替 ar
  • llvm-strip 代替 strip
  • make 升级到 4.3

这里简洁地介绍一些设定:

  • ar:用于生成静态库,类似打包器

  • as: 汇编器,变为 ‌.o 文件

  • strip: 裁剪符号,瘦身

  • LLD:llvm 的链接器

在 r22 之前,对于 arm64 默认的 NDK 链接器是 ld.bfd,其他架构是 ld.gold,而 r22 将默认链接器切换为 ld.lld

我们通过 readelf -p .comment 可以简单看到当前 so 编译时附带的一些信息,例如 clang version,LLD version 等。

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

另外,在 NDK r14 开始,其实 so 一般可以查看到用的是什么版本的 ndk ,我们可以先通过 readelf --sections -W 找到 .note.android.ident 的 Section number , 然后就可以通过 readelf -x num 看到 so 包含的 ndk version:

# 得到 1 这个 num
./aarch64-linux-android-readelf --sections -W  xxx.so
# -x 1 看这个 num 下的内容
./aarch64-linux-android-readelf -x 1  xxx.so

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

另外,曾经还遇到过 p_offset + p_filesz > file_size 的情况,这种时候基本也是工具链的问题,当时好像也是通过 llvm-strip 代替 GNU strip 解决了问题。

因为有的人可能并不知道自己的 so 是用什么编译,所以这部分「啰嗦」也可以帮助你更好了解你的 native library 的相关信息

此外,可以看到 21 上,典型的 bdf-ld/gold linker 上,对于 elf 一般都是分两段,.data.bss 一般在第二段 RW ;而在 22 上, LLD 上 .data.bss 被单独放在一个 LOAD segments,并且还多了 PHDR 程序头。

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

详细的具体原因这里就不再深入展开,这里更多是一个提示:如果出现「玄学」的报错,可能更多来自工具链的问题

所以目前看来,可以总结下,在 16K Page Size 上,llvm 的整体链路适配可能会比 GNU 更通畅,其实在更高版本的 NDK 里,GNU GCC 系列已经被完全移除,所以总结下:

  • 移除 stlport、gnustl 标准库的,使用 LLVM 的 libc++,如 c++_static、c++_shared
  • 使用较高版本 Clang/LLVM 替代 GCC/Binutils 进行编译适配
  • 低版本下 64k(0x10000) 对齐,其实并不一定对齐

毕竟例如 IJKPlayer 使用的 stlport STL ,已经十多年没更新了,关于页面大小的计算适配,还是在 2007 年的时候;另外 GNU 的 libstdc++ 与 LLVM Clang 编译器配合也不是很好。

为了证实这个问题,我们同样配置下,降级到 r21 ,重新打包,运行后,熟悉的 Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR) 又出现了,所以可以确认,问题核心是出在 NDK 编译链条。

所以,在 16K Page Size 的适配上,只要你没有 mmapsysconf 等写死 4096(0x1000) 地方的代码,那么完全就可以怀疑是 NDK 对应的工具链和标准库的问题

NDK 版本简介

事实上,如果你关注 NDK 的更新,你就会发现 NDK 的问题并不少,特别是在之前各个版本之间存在较大差异,这里我简单罗列下一些有关的更新:

  • NDK r11

    • 开始建议切换到 Clang
  • NDK r12

    • ndk-build 命令默认使用 Clang

    • make-standalone-toolchain.sh 脚本即将删除,需要尽快计划迁移到 make_standalone_toolchain.py,所以如果你的 ndk 已经删除了,可以在老版本中找到兼容方式:Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

  • NDK r13

    • GCC 不再受支持,它暂时不会从 NDK 中删除
  • NDK r14

    • GCC 弃用。但未从 NDK 中删除
  • NDK r16

    • 鼓励使用 libc++ 作为 C++ 标准库
  • NDK r17

    • libc++ 现在是 CMake 和独立工具链的默认 STL

    • 删除对 ARMv5 (armeabi)、MIPS 和 MIPS64 的支持

  • NDK r18

    • GCC 已被删除,包括 GNUSTL ,包括 gabi++ 和 stlport 一起被删除。
  • NDK r22

    • GNU binutils 已弃用,将在即将发布的 NDK 版本中被删除,包括 GNU assembler (as) ,如果使用 as 请转为 clang
    • LLD 现在是默认链接器
    • libc++ 升级
    • llvm-ar 代替 ar
    • llvm-strip 代替 strip
    • make 升级到 4.3
  • NDK r23

    • GNU binutils已被删除,GAS 将在下一版本中删除
    • 对 GDB 的支持已终止
    • NDK r23 是最后一个支持非 Neon 的版本
  • NDK r24

    • GNU 汇编器 (GAS) 已被移除

    • 非 Neon 设备不再受支持

  • NDK r27

    • 支持 APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true

我们再直观看 NDK 的 cxx-stl 目录,如下图所示,可以看到,r10 和 r21 的区别还是很大的。

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

所以升级 NDK 不要一下跨度太大,因为升级的成本真的很高,很容易让人放弃,而逐步升级,直到可以运行的方式会比较合适

Clang/LLVM 和 GCC/Binutils

接下来是简单的科普时间,不看科普的到这里其实就结束了,简单普及一些概念,免得不熟悉的情况下大家可能又会有更多疑问。

GCC 是 GNU 开发的编译器套件,是一套遵循 GNU 通用公共许可证(GPL)和 GNU 宽通用公共许可证(LGPL)发布的自由软件,是 GNU 和 Linux 系统的官方编译器。

Binutils( Binary Utilities) ,也就是 GNU 的二进制工具集,比如之前我们提到的 objdump、readelf 这一系列的工具就是 Binutils,而 GNU 就表示它们都是可以自由地使用的 GNU 软件,这些工具的目的是用于操作二进制文件。

二进制文件主要指 *.o 文件和 elf 执行文件,编译源代码的是 gcc,所以 Binutils 不包含 gcc

LLVM 包含了一系列模块化的编译器组件和工具链,可以在编译、运行、空闲时对程序语言和链接进行优化,并生成代码。

Clang 是基于 LLVM 用 C++ 编译的 C、C++、Objective-C 或 Objective-C++ 编译器,遵循 Apache 2.0 许可协议发布。

Clang 的设计初衷是提供一个可以替代 GCC 的前端编译器,因为 GCC 的发展不符合 Apple 的节奏和需要,同时受限于License,苹果公司无法使用 LLVM 在 GCC 基础上进一步提升代码生成质量,因此苹果公司决定从头编写 C、C++、Objective-C 语言的前端 Clang,以彻底替代GCC

所以不严谨的说,Clang/LLVM 是一套全新替代 GCC/Binutils 的存在。

那为什么会有这些东西存在?

这是因为很少有软件是直接用标准 C 编写的,大多其实是用类似 GCC C 编写,而 GCC 添加了一些非标准扩展,所以编译时会需要 GCC 的支持,当然或者 Clang 也在某种程度实现了对应的扩展。

所以总结下,不严谨又好理解的说:

Clang/LLVM 和 GCC/Binutils 一般是成对出现,Clang 和 GCC 主要是提供对于拓展的编译支持,而 LLVM 和 Binutils 则是提供对应的工具支持

当然这里讨论谁好谁坏没有意思,但是 Android 在很早之前,就开始采用 Clang/LLVM 进行编译,例如 Android 8.0 开始就只支持使用 Clang/LLVM 来编译 Android 系统。

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

从前面的 NDK 版本迭代也可以看到,NDK 一直在致力剥离 GCC/Binutils 相关的内容,而目前 Swift、Rust、Julia 等许多新编程语言都使用 LLVM 作为编译框架,而 LLVM 也是 Mac OS X、iOS、FreeBSD 、 Android 系统的默认编译器。

如果真要说,GCC 比 Clang 支持更多的传统语言和冷门架构,而新兴语言基本使用 LLVM 居多,如 Swift、Rust、Julia 和 Ruby

STL

接着我们再介绍 NDK 里的 STL,就是前面我们提到的,将 APP_STL 从 stlport_static 修改为 c++_static,这又是什么东西?

STL(Standard Template Library) 一般就是我们开发中称呼的标准模板库,例如 iterator 、allocator 就和它有关系:

STL 属于是单独开发,然后提交给 C++ 标准委员会进行审议并接纳,但它不是作为 C++ 标准的一部分开发的,也就是前面我们说到的扩展支持,所以它会有 GNU 和 LLVM 不同版本。

STL 更像是一种设计策略,它提供了标准库所期望的最基本功能,例如存储数据序列的能力,以及处理这些序列的能力。

STL 还提供了有用算法和容器的通用实现,例如容器提供了在程序中存储数据然后查找、排序和对该数据执行其他计算的简单方法:

std::sort(container.begin(), container.end());

那么一开始其实 STL 的选择有很多,每种选择下又分为静态和动态支持,如下图可以简单理解为:

  • system(default) 系统默认的 C++运行库
  • gabi++_static 静态链接的方式使用 gabi++
  • gabi++_shared 动态链接的方式使用 gabi++
  • stlport_static 静态链接的方式使用 stlport 版本的 STL
  • stlport_shared 动态链接的方式使用 stlport 版本的 STL
  • gnustl_static 静态链接的方式使用 gnustl 版本的 STL
  • gnustl_shared 动态链接的方式使用 gnustl 版本的 STL
  • c++_static 以静态链接的方式使用 LLVM libc++
  • c++_shared 以动态链接的方式使用 LLVM libc++

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

那么如果按照分类理解,其实就是:

  • system:默认最小的 C++ 运行库,这样生成的应用体积小,内存占用小,但部分功能将无法支持,只提供默认的一些固定标头。

  • gabi++:不支持 C++ 标准库,提供与默认运行时相同的标头,但加入了对异常处理和 RTTI 的支持

  • stlport:提供 C++ 的特性支持,它是开源项目 STLPort 的一个 android 移植版本

  • gnu-libstdc++:GNU 标准 C++ 运行时库,同样支持异常和 RTTI。

  • llvm-libc++:该版本是 LLVM libc++ 的一个移植版本,支持 C++ 的所有特性。

但是如果你现在看官网,其实只可以看到下方的选择,对应前面的 cxx-stl 目录,其实现在就只有 libc++system 可选,也就是你要完整的 C++ 运行时库,只能用 llvm 的 libc++ ,从 NDK r18 之后 libc++ 是唯一的 STL

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

对于 system ,其实它属于非完全 STL 版本,system 指的就是 Android 版本里的 /system/lib/libstdc++.so,它能提供基本的 c++ 运行支持, 但是属于删减能力版本。

虽然 systemlibc++ 都是 LLVM 的 c++ STL ,但是 libc++ 是基于NDK开发时,NDK 里已经编译好的完整库

例如,如果 NDK 开发的 App 用到 libc++_shared.so ,那么其实整个 .so 会被打包到 APK里,用到libc++_static.a 的情况下,.a 也是被包到 App 中,在发布应用时,完整的 STL 会跟随一起发布,不依赖Android 版本内部的 STL 。

虽然都是 llvm ,但是使用不同版本的 NDK 打包构建后的 App ,可能就使用着不同版本的 libc++ , 所以不同的 NDK 本身对于 16K Page Size 适配问题上,本来就可能存在差异化。

此外,这里有个需要注意的,一个 App 里,所有依赖项最好且只使用同一 STL ,例如:

你存在有依赖使用了 STL 的闭源第三方依赖项,那么你必须使用与依赖项相同的 STL,两个不同的 STL 构建的库可能会存在冲突,例如 std::string 在 libc++ 和 gnustl 就存在差异化。

最后

从官方对于 NDK 对 16K Page Size 提供的描述看,Android V 其实还是允许 OEM 厂商自己选择 16K 还是 4K ,而其实按照 Page Size 逻辑,16K 的 so 本来就兼容 4K 的设备,因为它 16 本身就是 4 的整数倍,所以我们也不需要同时构建 16K 和 4K 版本的库,只需要 16K 就够了

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

另外也有人在问, Google Play 计划明年就要求 16K Page Size 的出处是哪里,对于感兴趣的可以查阅:developer.android.com/guide/pract…

Android 15 上适配 16K Page Size 的填坑思路,以 IJKPlayer 为例子

所以通篇看下来,你要做的主要就是:

  • 确保代码里没有 mmapsysconf 等写死 4096(0x1000) 地方的代码(本篇第 N 次出现)
  • 确保不是假对齐,例如低版本 NDK 编译下的 0x10000(65536) 64k 对齐不一定可信
  • 4K 可运行的情况下, 16K 在确定 so 都是地址对齐的情况下,高度怀疑 NDK 问题
  • 升级 NDK or 工具链合集,首选升级为 Clang/LLVM 相关

而升级这些东西,了解文中的各种编译器和工具链基础是非常有必要的,至少你要知道出错的是什么,然后才能知道大概需要调整的方向。

适配 16K 的过程,其实就是一个「自我怀疑」的过程,可以说不同的「古老项目」,可能都存在不同的“玄学”问题,而解决这些问题的核心,是一个费时费力的体力活。

那么,你是否已经开始尝试适配了?什么,你说你没有源码?那么只能祈祷 Google 愿意在落地时折腾出来「混合 Page Size Running Time」 的东西了,不过这个可能性并不高,当然也不是没有,不过非虚拟化的混合 Page Size 的落地成本,着实感人

转载自:https://juejin.cn/post/7396306532671094793
评论
请登录