在我们基于游戏引擎cocos2d-x的Android游戏应用程序中,大部分代码都是用C++编写的,从Android 11开始,我们就遇到了一个非常奇怪和关键的问题:
当本机库在onLoadNativeLibraries中加载时,现在突然需要60+秒。在Android 11之前,它工作得很好,并在0.2到3秒内完成了装载。现在,当你开始游戏,你有一个60+秒的灰色屏幕。
我们已经知道在60秒失速结束后直接调用JNI_OnLoad。
下面是onLoadNativeLibraries函数的代码:
protected void onLoadNativeLibraries()
{
try
{
ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
Bundle bundle = ai.metaData;
String libName = bundle.getString("android.app.lib_name");
System.loadLibrary(libName); // line of 60 seconds stall
}
catch (Exception e)
{
e.printStackTrace();
}
}我们已经试过时间分析了,但没有成功。这说明它花了很多时间在这个功能上。此外,通过调试暂停不会带来任何进一步的线索。本机调试器在代码的C++端没有显示任何内容。
有没有人知道为什么会发生这种事,或者我们能想出什么办法?如能提供任何帮助,将不胜感激:)
发布于 2020-10-29 15:08:18
简短回答:
这是谷歌修复的Android 11中的一个bug,但尚未部署。
同时,如果您不关心在程序退出/库卸载时调用库中的静态和thread_local变量析构函数,则将标志-fno-c++-static-destructors传递给编译器。(关于使用clang注释的更细粒度的解决方案,请参见长答案)
我在我的项目(不是cocos2d)中使用了这个标志,没有问题,而且lib的加载速度比以前还要快。
长答案:
不幸的是,这是谷歌团队在android 11 (R)中引入的性能倒退。谷歌这里正在追踪这个问题。
总之,当调用System.loadLibrary()时,系统将使用atexit()为加载库中包含的每个C++全局变量注册一个析构函数。
自从Android 11 (R)之后,这个功能在android上的实现就有了变化。
当性能是许多C++全局变量时,这种变化会使性能急剧下降,这在cocos2d库中似乎是如此。
谷歌已经实现了修复https://android-review.googlesource.com/c/platform/bionic/+/1464716,但正如问题中所述:
这将不会在Android 11中最早在3月QPR,因为这不是一个安全问题,它将不会是强制性的原始设备制造商实际采取的修补程序。
谷歌团队还建议,通过删除或跳过全局变量上的析构函数,在应用程序级别设置一些解决办法:
https://stackoverflow.com/questions/64576236
复制相似问题