日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

KOOM原理分析之二KOOM

發布時間:2024/1/18 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 KOOM原理分析之二KOOM 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 資料
  • KOOM的總體架構
    • koom-demo
    • koom-java-leak
    • koom-native-leak
    • koom-koom-thread-leak
    • koom-monitor-base
    • kwai-android-base
    • kwai-unwind
    • shark
    • xhook
  • 分解步驟
    • 引起泄漏的地方
    • 注冊
    • 開啟循環startLoop
    • OOMMonitor中的dumpAndAnalysis
    • ForkJvmHeapDumper中的dump

資料

github/KOOM
快手客戶端穩定性體系建設
Android 中看似高大上的字節碼修改,這樣學就對了!

KOOM的總體架構

koom-demo


這個主要是給了多個例子, 尤其是里面給出了如何創建內存泄漏, 我覺得非常棒。

koom-java-leak

專門處理java的內存泄漏

koom-native-leak

專門處理native的內存泄漏

koom-koom-thread-leak

專門處理thread的內存泄漏

koom-monitor-base

一些工具類,

kwai-android-base

感覺跟工具類很像

kwai-unwind

shark

在LeakCanary中有這個庫

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)

開啟循環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")// 開啟新進程, 阻塞當前進程, 并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")// 開啟新進程, 阻塞當前進程, 并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.");// 創建子進程// pid返回值// 1。 返回子進程id給父進程:// 因為一個進程的子進程可能有多個,并且沒有一個函數可以獲得一個進程的所有子進程// 2。 返回給子進程值為0:// 一個進程只會有一個,所以子進程松獅可以調用getid以獲得當前進程id以調用getid獲得父進程id// 3。 出現錯誤,返回負值:// 當前進程數已經達到系統規定的上限,這是errno的值被設置為EAGAIN// 系統內存不足,這時errno的值被設置為ENOMEMint pid = suspendAndFork(); // 創建自線程并掛起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;}

總結

以上是生活随笔為你收集整理的KOOM原理分析之二KOOM的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。