KOOM原理分析之二KOOM
生活随笔
收集整理的這篇文章主要介紹了
KOOM原理分析之二KOOM
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- 資料
- KOOM的總體架構(gòu)
- koom-demo
- koom-java-leak
- koom-native-leak
- koom-koom-thread-leak
- koom-monitor-base
- kwai-android-base
- kwai-unwind
- shark
- xhook
- 分解步驟
- 引起泄漏的地方
- 注冊
- 開啟循環(huán)startLoop
- OOMMonitor中的dumpAndAnalysis
- ForkJvmHeapDumper中的dump
資料
github/KOOM
快手客戶端穩(wěn)定性體系建設(shè)
Android 中看似高大上的字節(jié)碼修改,這樣學(xué)就對了!
KOOM的總體架構(gòu)
koom-demo
這個(gè)主要是給了多個(gè)例子, 尤其是里面給出了如何創(chuàng)建內(nèi)存泄漏, 我覺得非常棒。
koom-java-leak
專門處理java的內(nèi)存泄漏
koom-native-leak
專門處理native的內(nèi)存泄漏
koom-koom-thread-leak
專門處理thread的內(nèi)存泄漏
koom-monitor-base
一些工具類,
kwai-android-base
感覺跟工具類很像
kwai-unwind
shark
在LeakCanary中有這個(gè)庫
xhook
https://github.com/iqiyi/xHook
分解步驟
引起泄漏的地方
注冊
override fun init(application: Application) {val config = CommonConfig.Builder().setApplication(application) // Set application.setVersionNameInvoker { "1.0.0" } // Set version name, java leak feature use it.build()MonitorManager.initCommonConfig(config).apply { onApplicationCreate() } }val config = OOMMonitorConfig.Builder().setThreadThreshold(50) //50 only for test! Please use default value!.setFdThreshold(300) // 300 only for test! Please use default value!.setHeapThreshold(0.9f) // 0.9f for test! Please use default value!.setVssSizeThreshold(1_000_000) // 1_000_000 for test! Please use default value!.setMaxOverThresholdCount(1) // 1 for test! Please use default value!.setAnalysisMaxTimesPerVersion(3) // Consider use default value!.setAnalysisPeriodPerVersion(15 * 24 * 60 * 60 * 1000) // Consider use default value!.setLoopInterval(5_000) // 5_000 for test! Please use default value!.setEnableHprofDumpAnalysis(true).setHprofUploader(object : OOMHprofUploader {override fun upload(file: File, type: OOMHprofUploader.HprofType) {MonitorLog.e("OOMMonitor", "todo, upload hprof ${file.name} if necessary")}}).setReportUploader(object : OOMReportUploader {override fun upload(file: File, content: String) {MonitorLog.i("OOMMonitor", content)MonitorLog.e("OOMMonitor", "todo, upload report ${file.name} if necessary")}}).build() MonitorManager.addMonitorConfig(config)開啟循環(huán)startLoop
open fun startLoop(clearQueue: Boolean = true,postAtFront: Boolean = false,delayMillis: Long = 0L ) {if (clearQueue) getLoopHandler().removeCallbacks(mLoopRunnable)if (postAtFront) {getLoopHandler().postAtFrontOfQueue(mLoopRunnable)} else {getLoopHandler().postDelayed(mLoopRunnable, delayMillis)}mIsLoopStopped = false }private val mLoopRunnable = object : Runnable {override fun run() {if (call() == LoopState.Terminate) {return}if (mIsLoopStopped) {return}getLoopHandler().removeCallbacks(this)getLoopHandler().postDelayed(this, getLoopInterval())} }override fun call(): LoopState {if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP|| Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {return LoopState.Terminate}if (mHasDumped) {return LoopState.Terminate}return trackOOM() }private fun dumpAndAnalysis() {MonitorLog.i(TAG, "dumpAndAnalysis")runCatching {if (!OOMFileManager.isSpaceEnough()) {MonitorLog.e(TAG, "available space not enough", true)return@runCatching}if (mHasDumped) {return}mHasDumped = trueval date = Date()val jsonFile = OOMFileManager.createJsonAnalysisFile(date)val hprofFile = OOMFileManager.createHprofAnalysisFile(date).apply {createNewFile()setWritable(true)setReadable(true)}MonitorLog.i(TAG, "hprof analysis dir:$hprofAnalysisDir")// 開啟新進(jìn)程, 阻塞當(dāng)前進(jìn)程, 并dumpForkJvmHeapDumper().run {dump(hprofFile.absolutePath)}MonitorLog.i(TAG, "end hprof dump", true)Thread.sleep(1000) // make sure file synced to disk.MonitorLog.i(TAG, "start hprof analysis")// 開始分析堆存儲文件,并解析成jsonstartAnalysisService(hprofFile, jsonFile, mTrackReasons.joinToString())}.onFailure {it.printStackTrace()MonitorLog.i(TAG, "onJvmThreshold Exception " + it.message, true)}}OOMMonitor中的dumpAndAnalysis
private fun dumpAndAnalysis() {MonitorLog.i(TAG, "dumpAndAnalysis")runCatching {if (!OOMFileManager.isSpaceEnough()) { // 是否超過容量MonitorLog.e(TAG, "available space not enough", true)return@runCatching}if (mHasDumped) {return}mHasDumped = trueval date = Date()val jsonFile = OOMFileManager.createJsonAnalysisFile(date)val hprofFile = OOMFileManager.createHprofAnalysisFile(date).apply {createNewFile()setWritable(true)setReadable(true)}MonitorLog.i(TAG, "hprof analysis dir:$hprofAnalysisDir")// 開啟新進(jìn)程, 阻塞當(dāng)前進(jìn)程, 并dumpForkJvmHeapDumper().run {dump(hprofFile.absolutePath)}MonitorLog.i(TAG, "end hprof dump", true)Thread.sleep(1000) // make sure file synced to disk.MonitorLog.i(TAG, "start hprof analysis")// 開始分析堆存儲文件,并解析成jsonstartAnalysisService(hprofFile, jsonFile, mTrackReasons.joinToString())}.onFailure {it.printStackTrace()MonitorLog.i(TAG, "onJvmThreshold Exception " + it.message, true)}}ForkJvmHeapDumper中的dump
@Overridepublic boolean dump(String path) {MonitorLog.i(TAG, "dump " + path);if (!soLoaded) {MonitorLog.e(TAG, "dump failed caused by so not loaded!");return false;}if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP|| Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {MonitorLog.e(TAG, "dump failed caused by version not supported!");return false;}boolean dumpRes = false;try {MonitorLog.i(TAG, "before suspend and fork.");// 創(chuàng)建子進(jìn)程// pid返回值// 1。 返回子進(jìn)程id給父進(jìn)程:// 因?yàn)橐粋€(gè)進(jìn)程的子進(jìn)程可能有多個(gè),并且沒有一個(gè)函數(shù)可以獲得一個(gè)進(jìn)程的所有子進(jìn)程// 2。 返回給子進(jìn)程值為0:// 一個(gè)進(jìn)程只會有一個(gè),所以子進(jìn)程松獅可以調(diào)用getid以獲得當(dāng)前進(jìn)程id以調(diào)用getid獲得父進(jìn)程id// 3。 出現(xiàn)錯(cuò)誤,返回負(fù)值:// 當(dāng)前進(jìn)程數(shù)已經(jīng)達(dá)到系統(tǒng)規(guī)定的上限,這是errno的值被設(shè)置為EAGAIN// 系統(tǒng)內(nèi)存不足,這時(shí)errno的值被設(shè)置為ENOMEMint pid = suspendAndFork(); // 創(chuàng)建自線程并掛起if (pid == 0) {// Child processDebug.dumpHprofData(path);exitProcess();} else if (pid > 0) {// Parent processdumpRes = resumeAndWait(pid);MonitorLog.i(TAG, "notify from pid " + pid);}} catch (IOException e) {MonitorLog.e(TAG, "dump failed caused by " + e.toString());e.printStackTrace();}return dumpRes;}總結(jié)
以上是生活随笔為你收集整理的KOOM原理分析之二KOOM的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于3D投影
- 下一篇: 图标设计,制作一款紫色的树叶水滴怪兽图标