【安卓源码阅读】简单追溯几个内存回收的守护线程

1. 背景

以前在解anr问题的时候常常会看trace,经常看到无响应进程有类似以下的trace堆栈,但是没有机会去了解以下这些守护线程。

正好最近我们在虚拟机回收内存的时候做了一些逻辑,所以简单分析一下。

"ReferenceQueueDaemon" daemon prio=5 tid=10 Waiting
  | group="system" sCount=1 dsCount=0 flags=1 obj=0x12dc03d8 self=0x73e5721800
  | sysTid=6355 nice=4 cgrp=default sched=0/0 handle=0x73876a7d50
  | state=S schedstat=( 5968594 3597186 25 ) utm=0 stm=0 core=1 HZ=100
  | stack=0x73875a5000-0x73875a7000 stackSize=1039KB
  | held mutexes=
  at java.lang.Object.wait(Native method)
  - waiting on <0x00c7e21d> (a java.lang.Class<java.lang.ref.ReferenceQueue>)
  at java.lang.Object.wait(Object.java:442)
  at java.lang.Object.wait(Object.java:568)
  at java.lang.Daemons$ReferenceQueueDaemon.runInternal(Daemons.java:218)
  - locked <0x00c7e21d> (a java.lang.Class<java.lang.ref.ReferenceQueue>)
  at java.lang.Daemons$Daemon.run(Daemons.java:140)
  at java.lang.Thread.run(Thread.java:919)
​
"FinalizerDaemon" daemon prio=5 tid=11 Waiting
  | group="system" sCount=1 dsCount=0 flags=1 obj=0x12dc0450 self=0x73e5723400
  | sysTid=6356 nice=4 cgrp=default sched=0/0 handle=0x738659ed50
  | state=S schedstat=( 6188228 2839739 24 ) utm=0 stm=0 core=1 HZ=100
  | stack=0x738649c000-0x738649e000 stackSize=1039KB
  | held mutexes=
  at java.lang.Object.wait(Native method)
  - waiting on <0x0b6e4c92> (a java.lang.Object)
  at java.lang.Object.wait(Object.java:442)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:190)
  - locked <0x0b6e4c92> (a java.lang.Object)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:211)
  at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:274)
  at java.lang.Daemons$Daemon.run(Daemons.java:140)
  at java.lang.Thread.run(Thread.java:919)
​
"FinalizerWatchdogDaemon" daemon prio=5 tid=12 Waiting
  | group="system" sCount=1 dsCount=0 flags=1 obj=0x12dc04c8 self=0x73e572a000
  | sysTid=6357 nice=4 cgrp=default sched=0/0 handle=0x7385495d50
  | state=S schedstat=( 2227916 6292450 28 ) utm=0 stm=0 core=1 HZ=100
  | stack=0x7385393000-0x7385395000 stackSize=1039KB
  | held mutexes=
  at java.lang.Object.wait(Native method)
  - waiting on <0x04374663> (a java.lang.Daemons$FinalizerWatchdogDaemon)
  at java.lang.Object.wait(Object.java:442)
  at java.lang.Object.wait(Object.java:568)
  at java.lang.Daemons$FinalizerWatchdogDaemon.sleepUntilNeeded(Daemons.java:342)
  - locked <0x04374663> (a java.lang.Daemons$FinalizerWatchdogDaemon)
  at java.lang.Daemons$FinalizerWatchdogDaemon.runInternal(Daemons.java:322)
  at java.lang.Daemons$Daemon.run(Daemons.java:140)
  at java.lang.Thread.run(Thread.java:919)

2. 分析

直接先简单介绍一下,FinalizerWatchdogDaemon,FinalizerDaemon和ReferenceQueueDaemon三个类都继承了Daemon类,并实现了Daemon类的runInternal方法。Daemon类的run方法会执行对应子类的runInternal方法,简单看了一下Daemon守护的start方法就会调用runInternal方法,这些守护线程开启的时候都会执行对应的runInternal方法。

在这三个守护线程开启后,就会走到上面的“堆栈”显示的状态。

三个守护线程wait的地方,具体是:

  1. FinalizerDaemon, libcore/libart/src/main/java/java/lang/Daemons.java, finalizingReference = (FinalizerReference<?>)queue.remove();
  1. ReferenceQueueDaemon, libcore/libart/src/main/java/java/lang/Daemons.java, ReferenceQueue.class.wait();
  2. FinalizerWatchdogDaemon, libcore/libart/src/main/java/java/lang/Daemons.java, sleepUntilNeeded()

这三个守护线程都调用的Object.wait方法等待,其分别等待的锁对象是:

  1. FinalizerDaemon, 等待java/lang/ref/ReferenceQueue.java的lock对象;
  2. ReferenceQueueDaemon,等待ReferenceQueue的类对象;
  3. FinalizerWatchdogDaemon,等待FinalizerWatchdogDaemon的的实例对象;

3. runFinalization

简单追溯代码之后,发现System.runFinalization方法可以notify上面三个守护线程。我是反向追溯的,但是下面代码的分析还是正向来贴把。

java/lang/System.java    runFinalization()
--->java/lang/Runtime.java   runFinalization()
        --->libcore/libart/src/main/java/dalvik/system/VMRuntime.java    runFinalization()
            --->java/lang/ref/FinalizerReference.java enqueueSentinelReference(sentinel)
                --->java/lang/ref/ReferenceQueue.java static void add(Reference<?> list)
                    

在java/lang/ref/ReferenceQueue.java的add的方法中,会调用“ReferenceQueue.class.notifyAll()”唤醒等待在ReferenceQueue类对象的所有线程,其中就有ReferenceQueueDaemon线程。

而ReferenceQueueDaemon被唤醒之后,又会唤醒等待在ReferenceQueue.java的lock对象的FinalizerDaemon线程。接着会调用“FinalizerWatchdogDaemon.INSTANCE.wakeUp()”唤醒FinalizerWatchdogDaemon线程。

最后,当FinalizerWatchdogDaemon守护线程超时之后,则会调用finalizerTimedOut方法做超时后的逻辑。

真正干活的是FinalizerDaemon线程,做Finalize的逻辑在

libcore/libart/src/main/java/java/lang/Daemons.java    doFinalize(finalizingReference);
    java/lang/Daemons.java   object.finalize();

4.结语

其实在进行这部分代码的追溯之前,我也没想到会追溯到runFinalization方法。

但是工作中经常需要在各个代码块中加逻辑,有时候加了一些逻辑之后,顺便解决一下之前工作中的困惑,也是挺好的。

最后提一点,网上有人喜欢在runFinalization之前先调用一下gc方法,其实没有必要,在runFinalization方法的内部,会帮你gc了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android应用源码安卓源码(172个合集),可以做为你的学习参考。 365MobileSecretary v1.0.6(365手机助手AIDL) 888个经典 Logo.rar AdXmpp(Openfire+asmack+spark) .zip AidlDemo(简单aidl的例子) aidl跨进程调用.rar andbatdog电池监控.rar andbatdog监视电池.rar andricoFacebook客户端.rar Android Gamex分析报告.rar Android 英语单词记忆程序源码 AndroidPdfViewerPDF查看器.zip AndroidPlayer(仿酷狗播放器).tar androidtalk_2010_11_17【Sundy系列】全看懂了-加两年经验-语音朗读-语音识别-语音.rar Android下的信息客户端 WhisperSystems-TextSecure.zip Android与js交互.rar Android中监听电话状态.rar Android之Wifi学习教程.rar Android之用PopupWindow实现弹出菜单.rar android在wifi下手机与电脑的socket通信.rar android多线程断点下载.rar Android手机一键Root原理分析.zip Android手机的VoIP客户端 Sipdroid.rar Android有未接来电后处理(判断未接来电).rar Android模仿乐淘的应用程序分析源码.zip Android游戏源码——忍者快跑.rar Android自动发送短信.rar Android自动开关机实现.rar Android视频采集+RTSP完整代码(可用) Android远程登录含有loading登录效.zip Angle v1.0_2D游戏引擎.ZIP BOOK看遍所有UI控件.7z BrewClock闹钟.zip BTAndroidWebViewSelection(webview选择文字) cellmap v2.0 基站查询定位导航系统 .rar DialogShow.rar dialog去除边框代码.rar DocumentViewer(PDF阅读器) douBanList(滚动到底部加载新的,软缓存,懒加载) Droid Wall 手机防火墙.zip FBReader修改epub快速加载.rar FiveChess五子棋.zip Flashlight灯光.zip GetSDTree(简单SD卡文件浏览器) hotel宾馆系统.zip ImageView 图片循环跑马灯的效果.rar ipcamera-for-android 手机变成IP Camera.rar jamendo-开源在线音乐.rar jchat4android手机聊天程序.rar LoginXml.rar MineSweeper由java实现.zip miniTwitter登录界面.rar MyAppWeixin(仿微信界面) MyBrowser(简单网页浏览器) Myjob3(图片剪辑功能).rar OPENG开发的示例代码.rar OpenSudoku一个简单的九宫格数独游戏.zip OssSystem(OA系统图书管理简单版).rar Phonegap+HTML5+CSS3+jQuer简单界面模板示例及源码.rar ProgressBar 几乎全部的用法.rar QQ_UI之分类菜单DEMO.zip QQ的登录界面 源代码 .zip quitesleep手机电话功能软件.rar rokon_src_2-0-3_游戏引擎.zip scientific-calculator-for-android( 功能强大的科学计算器).zip SeeJoPlayer(播放器).7z SipDroid客户端源码.rar sipdroid语音及视频通话.rar tablelogin(登陆界面).rar TankWar坦克大战.zip telecapoland-jamendo-android-6cd07fb(国外开源音乐播放器) TorProxy应用实现了Android手机无线电电传通讯(TOR).rar UI设计之 仿做蘑菇街UI设计 源码.zip ViewPager-实现左右两个屏幕的切换.rar VIEW双缓冲与SurfaceView比较.zip weibo4andriod-2011-01-14.zip WordPress for Android zirco-browser浏览器源码.rar Zirco-browser:超越海豚的开源浏览器.rar zz-doctor中医大夫助

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值