【泄漏类】android7.0 system_server发生global reference table overflow问题分析
1、问题描述
旋转屏测试5~6小时system_server发生abort,手机重启导致测试停止,android7.0平台多个项目都有此问题爆出。
和测试同事了解旋转屏幕在settings界面进行操作概率较高。
2、问题分析
从tombstone分析system_server abort原因是global reference table overflow 。
pid: 3749, tid: 8164, name:Binder:3749_E >>> system_server<<< signal 6 (SIGABRT), code -6 (SI_TKILL), faultaddr -------- Abort message: 'vendor/intel/art-extension/runtime/indirect_reference_table.cc:125]JNI ERROR (app bug): global reference table overflow (max=51200)' rax0000000000000000 rbx00007f0567b034f8 rcx00007f0590c28f37 rdx 0000000000000006 rsi0000000000001fe4 rdi 0000000000000ea5 r8 ffffffffffffffd8 r9 00007f0567b01790 r10 0000000000000008 r11 0000000000000206 r120000000000001fe4 r130000000000000006 r1400007f0567b024b0 r15 00007f05902d0800 cs 0000000000000033 ss 000000000000002b rip00007f0590c28f37 rbp000000000000000b rsp00007f0567b02358 eflags 0000000000000206 backtrace: #00pc 000000000008ef37 /system/lib64/libc.so (tgkill+7) #01pc 000000000008b952 /system/lib64/libc.so (pthread_kill+66) #02pc 0000000000030371 /system/lib64/libc.so(raise+17) #03pc 000000000002875e /system/lib64/libc.so (abort+78) #04pc 0000000000572f29 /system/lib64/libart.so (_ZN3art7Runtime5AbortEv+361) #05pc 00000000001d2091 /system/lib64/libart.so (_ZN3art10LogMessageD1Ev+817) #06pc 000000000036b5dd /system/lib64/libart.so(_ZN3art22IndirectReferenceTable3AddEjPNS_6mirror6ObjectE+669) #07pc 00000000004201e9 /system/lib64/libart.so(_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadEPNS_6mirror6ObjectE+57) #08pc 000000000045cd3b /system/lib64/libart.so |
此类泄漏问题可能是由于naitve层代码导致也可能是java层代码导致,需要具体分析log。
A001-01 23:45:55.469 3749 8164 F art : vendor/intel/art-extension/runtime/indirect_reference_table.cc:125] 6202 of com.android.server.print.UserState$4 (6202 unique instances) A001-01 23:45:55.469 3749 8164 F art :vendor/intel/art-extension/runtime/indirect_reference_table.cc:125] 6198 of com.android.server.print.UserState$3 (6198 unique instances) A001-01 23:45:55.465 3749 8164 F art :vendor/intel/art-extension/runtime/indirect_reference_table.cc:125] 18626 of android.os.RemoteCallbackList$Callback (18626 unique instances) A001-01 23:45:55.463 3749 8164 F art :vendor/intel/art-extension/runtime/indirect_reference_table.cc:125] 19147 of java.lang.ref.WeakReference(19147 unique instances) 18626 + 19147+ 6202 + 6198 = 50173 从log看是上面4个类型对象实例过多导致,这里4个对象的引用和是50173,加上其他的对象引用就大于了我们设置的阀值51200,就会主动触发abort。 |
从上面log我们不能完全确定是那里的代码逻辑有问题,因为UserState、RemoteCallbackList、WeakReference都是比较公共的类。我们需要通过发生问题时的调用栈来看是哪里有问题。
先看RemoteCallbackList相关调用栈如下 A001-01 23:45:55.381 3749 8164 E : native trace: A001-01 23:45:55.381 3749 8164 E : #00 pc000000000045cd3b /system/lib64/libart.so(_ZN3art3JNI12NewGlobalRefEP7_JNIEnvP8_jobject+267) A001-01 23:45:55.381 3749 8164 E : #01 pc000000000010f303 /system/lib64/libandroid_runtime.so A001-01 23:45:55.381 3749 8164 E : #02 pc000000000004ef8b /data/dalvik-cache/x86_64/system@framework@boot.oat (offset 0x2c30000) A001-01 23:45:55.381 3749 8164 E : java trace: A001-01 23:45:55.381 3749 8164 E : at android.os.BinderProxy.linkToDeath(Nativemethod) A001-01 23:45:55.381 3749 8164 E : atandroid.os.RemoteCallbackList.register(RemoteCallbackList.java:114) A001-01 23:45:55.381 3749 8164 E : - locked <0x0fcaf6ec> (a android.util.ArrayMap) A001-01 23:45:55.381 3749 8164 E : atandroid.os.RemoteCallbackList.register(RemoteCallbackList.java:78) A001-01 23:45:55.381 3749 8164 E : atcom.android.server.wallpaper.WallpaperManagerService.getWallpaper(WallpaperManagerService.java:1276) A001-01 23:45:55.381 3749 8164 E : - locked <0x072f3ab5> (ajava.lang.Object) A001-01 23:45:55.381 3749 8164 E : atandroid.app.IWallpaperManager$Stub.onTransact(IWallpaperManager.java:127) A001-01 23:45:55.381 3749 8164 E : atandroid.os.Binder.execTransact(Binder.java:591) 由于RemoteCallbackList相关的引用有18626,所以我们先来处理这个 |
从上面的调用栈看可以确认是settings与system_server进行binder通信,而binder通信过程中system_server的RemoteCallbackList实例是通过getWallpaper注册的,这里实例多通过代码分析是settings中转屏会调用hasWallpaperSet,这里会和WallpaperManagerService进行binder通信,注册对应的callBack实例,由于长时间转屏,就会导致实例堆积没有释放,进而越来越多。对应代码如下
settings中在调用异步线程后台执行会调用isSuggestionComplete,这里会触发getWallpaper注册RemoteCallback DashboardSummary.java 269 protected List<Tile> doInBackground(Void... params) { 270 List<Tile> suggestions = mSuggestionParser.getSuggestions(); 271 for (int i = 0; i < suggestions.size(); i++) { 272 if (mSuggestionsChecks.isSuggestionComplete(suggestions.get(i))){ 273 mAdapter.disableSuggestion(suggestions.get(i)); 274 suggestions.remove(i--); 275 } 276 } packages/apps/Settings/src/com/android/settings/dashboard/SuggestionsChecks.java 99 private boolean hasWallpaperSet() { 100 IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE); 101 IWallpaperManager service = Stub.asInterface(b); 102 try { 103 return service.getWallpaper(mCallback, WallpaperManager.FLAG_SYSTEM, 104 new Bundle(),mContext.getUserId()) != null; 105 } catch (RemoteException e) { 106 } 这里有定义对应的callback实例 110 private final IWallpaperManagerCallback mCallback = new IWallpaperManagerCallback.Stub() ...... server 端,当cb不为null时会注册cb函数,cb实例过多导致RemoteCallbackList过多 |
这里我们找到了第一个实例过多的代码,从代码看是google 原生的代码,这里的代码存在漏洞,如果长时间转屏就会导致系统发生实例过多消耗过多的内存,造成泄漏。这里修改方法有多种不做详细赘述。
下面我们来看第二类UserState实例多问题,看下我们打印的调用栈
A001-01 23:45:55.469 3749 8164 F art : vendor/intel/art-extension/runtime/indirect_reference_table.cc:125] 6202 of com.android.server.print.UserState$4 (6202 unique instances) 从上面log可以知道这里userState实例有两类 A001-02 09:28:10.277 3414 3414 E : native trace: A001-02 09:28:10.277 3414 3414 E : #00 pc 000000000045cd2b /system/lib64/libart.so (_ZN3art3JNI12NewGlobalRefEP7_JNIEnvP8_jobject+267) A001-02 09:28:10.277 3414 3414 E : at android.os.Binder.execTransact(Binder.java:591) A001-02 09:28:10.278 3414 3414 E : native trace: |
从调用栈信息可知还是settings与system_server有binder通信导致,system_server中积累了大量的实例对象。那么这是哪里导致的实例多的问题呢?
插播小知识:UserState$3、UserState$4这里UserState类后面跟$符加数字表示UserState类中包含的内部类,UserState类序号是1,之后的内部类是2、3、4等。代码参见frameworks\base\services\print\java\com\android\server\print\UserState.java
这样我们根据序号也可以确定是调用的那个内部类中的方法。
下面结合代码分析,先分析UserState$3的代码
packages/apps/Settings/src/com/android/settings/print/PrintJobSettingsFragment.java 52 private final PrintJobStateChangeListener mPrintJobStateChangeListener = 58 }; packages/apps/Settings/src/com/android/settings/print/PrintJobSettingsFragment.java 103 } 之后会调用 frameworks/base/core/java/android/print/PrintManager.java mPrintJobStateChangeListeners.put(listener, wrappedListener); 接下来调用下面代码 frameworks/base/services/print/java/com/android/server/print/PrintManagerService.java public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener, int appId, int userId) throws RemoteException { } 最终调用到UserState类中的addPrintJobStateChangeListener,也就是我们出问题时看到的调用栈 562 } 通过UserState类中的PrintJobStateChangeListenerRecord内部类可以看出,这里有注册一个死亡通知链linkToDeath frameworks/base/services/print/java/com/android/server/print/UserState.java private abstract class PrintJobStateChangeListenerRecord implements DeathRecipient { public PrintJobStateChangeListenerRecord(@NonNull IPrintJobStateChangeListener listener, } static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list);//这里会调用env->NewGlobalRef(object)建立引用 frameworks/base/core/jni/android_util_Binder.cpp |
从上面的代码流程可以看出,当settings在旋转屏是会启动print相关服务注册一个listener,这个linstener只有在binderDied中调用onBinderDied时才会remove对应的listener,而在旋转屏幕过程中这个组测的listener明显是不会被remove掉,所以长时间旋转这里就会导致注册多个listener,一直不释放就会导致system_server中的GlobalRef对象增多,只要测试时间够长就会引发当前问题。此流程为google原生。修改就是及时remove掉通过注册listener所增加的GlobalRef对象就可以解决。
UserState$4的代码流程和UserState$3的流程和问题点一样,修改方法相同,代码如下
frameworks/base/core/java/android/print/PrintServicesLoader.java 79 protected void onStartLoading() { 80 mHandler = new MyHandler(); 81 mListener = new PrintManager.PrintServicesChangeListener() { 82 @Override public void onPrintServicesChanged() { 83 queueNewResult(); 84 } 85 }; 86 87 mPrintManager.addPrintServicesChangeListener(mListener); 88 89 // Immediately deliver a result 90 deliverResult(mPrintManager.getPrintServices(mSelectionFlags)); 91 } frameworks/base/core/java/android/print/PrintManager.java frameworks/base/services/print/java/com/android/server/print/UserState.java |
修改完前三个问题后,进行复测,问题不复现。至此问题解决。
【泄漏类】android7.0 system_server发生global reference table overflow问题分析相关推荐
- local reference table overflow 内存泄露
local reference table overflow JNI层coding经常会遇到ReferenceTable overflow问题,特别是当jni函数被反复调用上千上万次的时候,现汇总如下 ...
- Android稳定性系列9 global reference限制策略
一 概述 global reference使用不当,就会引发lobal reference overflow异常问题,为了解决这个问题,从Android 9.0开始新增了限制策略. 先来看看虚拟机的一 ...
- Android7.0反射类找不到的问题
Java中使用反射的地方较多,尤其是各种框架中.最近在Android7.0的项目中遇到个问题很奇怪,反射使用的类找不到了,但是编译的时候没问题啊.然后在代码中使用非反射的方式调用代码也是没有问题的,这 ...
- Android7.0 发生的android.os.FileUriExposedException错误
在Android7.0的系统上调用系统相机拍照或者进相册,便会出现android.os.FileUriExposedException错误.这是安卓7.0以上版本,做了一些系统权限更改,为了提高私有文 ...
- Android 系统(40)--Android7.0 PowerManagerService亮灭屏分析(一)
Android7.0 PowerManagerService亮灭屏分析(一) 可以导致手机亮灭屏的因素有多种,而在本文中主要讲解按power键亮灭屏过程以及来电亮屏.在亮灭屏过程power中主要的实现 ...
- Android7.0适配方案
1安装时解析错误 我们的App通常会有检查更新的功能.用户在收到提示更新并且下载完后,会自动打开安装页面让用户来去安装.这时就会出现安装错误的问题,这类的问题的可能性比较多.比如较低版本的App想要覆 ...
- Android 系统(41)---Android7.0 PowerManagerService亮灭屏分析(二)
Android7.0 PowerManagerService亮灭屏分析(二) 3029 在PowerManagerService中对各种状态进行判断后,将其数值封装进DisplayPowerReque ...
- Android7.0关机流程分析
在长按power键时系统会弹出对话框,让用户选择关机, 重启或者其他模式. 在本文中重点讲解系统关机流程. 让大家了解在系统关机过程都做了哪些事情,而导致关机慢又有那些主要的原因.在Android7. ...
- Android7.0以上多系统语言的国际化适配
前言 近期偶然发现一个问题,我们的应用在7.0以上的个别机型上,会遇到国际化不对的问题,现象是:手机明明设置了中文,应用却可能显示成英文. 问题分析 问题机型:三星s8 plus 系统版本:Andro ...
最新文章
- Business Contact Mnanager for Outlook2010之二:常用基本功能
- [导入]web2.0中流行的设计元素:颜色
- 使用freemarker生成xml模板
- ci github 通知_GitHub 欢迎一切 CI 工具
- bxl类型封装转换为AD库封装
- vb连接oracle 工程,VB 连接Oracle数据库
- CIKM 2020 | FANG:利用社会语境及其图表示进行假新闻检测
- PCIe扫盲——PCI总线的三种传输模式
- 图-介绍(intro-Graph)
- js中文汉字按拼音排序
- mysql的binlog太大太多占用大量磁盘的解决
- java无法解析zip
- 安卓培训机构排名!这篇文章可以满足你80%日常工作!跳槽薪资翻倍
- 【Autopsy数字取证篇】Autopsy案例创建与镜像分析详细教程
- 自动在副屏/虚拟屏启动100%鲜橙汁 | 可用于上班摸鱼
- FPGA信号处理--多相滤波器(二)
- Restful风格设计
- PDF转CAD软件使用的便捷操作步骤
- [VisionPro] C#脚本介绍
- Mac——技巧:用“提醒事项”将任务分配给其他人
热门文章
- 【安卓小程序】app 首页
- 【深度学习】:非极大值抑制(NMS)详解
- 【CSDN竞赛第25期】赢热门图书《千脑智能》和定制周边
- GOM引擎传奇中增加会员时间的脚本教程分享
- 游戏引擎Easy2D-教程-简单绘画-蜡笔(基于版本V2.1.14)
- python matplotlib pyplot方法_Matplotlib.pyplot 常用方法
- java javax org_java mail程序--ClassNotFoundException:javax.mail.Address
- python调用大漠getcursorpos,GetCursorPos()函数
- Oracle 函数使用:CURSOR游标简单案例
- squid SwitchyOmega 实现浏览器代理切换