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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

koom 源码分析之 koom-monitor-base

發(fā)布時(shí)間:2024/1/18 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 koom 源码分析之 koom-monitor-base 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.LoopMonitor開啟單獨(dú)線程每隔1s監(jiān)聽一次

abstract class LoopMonitor<C> : Monitor<C>(), Callable<LoopMonitor.LoopState> {companion object {private const val DEFAULT_LOOP_INTERVAL = 1000L}//是否停止了//https://www.jianshu.com/p/3963e64e7fe7//在kotlin中沒有volatile關(guān)鍵字,但是有@Volatile注解,@Volatile//@Volatile將把JVM支持字段標(biāo)記為volatileprivate var mIsLoopStopped = true//單獨(dú)線程private val mLoopRunnable = object : Runnable {override fun run() {//如果call返回Terminate則停止if (call() == LoopState.Terminate) {return}if (mIsLoopStopped) {return}getLoopHandler().removeCallbacks(this)getLoopHandler().postDelayed(this, getLoopInterval())}}//開啟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}//停止open fun stopLoop() {mIsLoopStopped = truegetLoopHandler().removeCallbacks(mLoopRunnable)}//1s中protected open fun getLoopInterval(): Long {return DEFAULT_LOOP_INTERVAL}//一個(gè)開啟消息循環(huán)線程的Handlerprotected open fun getLoopHandler(): Handler {return commonConfig.loopHandlerInvoker()}sealed class LoopState {//兩個(gè)狀態(tài)Continueobject Continue : LoopState()//兩個(gè)狀態(tài)Terminateobject Terminate : LoopState()} }

2.LoopThread開辟單獨(dú)線程

//用object 修飾的類為靜態(tài)類,里面的方法和變量都為靜態(tài)的。 internal object LoopThread : HandlerThread("LoopThread", THREAD_PRIORITY_BACKGROUND) {init {start()}internal val LOOP_HANDLER = Handler(LoopThread.looper) }

3.CommonConfig默認(rèn)文件夾,SharedPreferences,log,加載so,線程池等

class CommonConfig private constructor(// MonitorManager common propertiesval application: Application,// Custom FileManager or sharedPreferencesval rootFileInvoker: (String) -> File,//默認(rèn)文件夾val sharedPreferencesInvoker: (String) -> SharedPreferences,val sharedPreferencesKeysInvoker: (SharedPreferences) -> Set<String>,// MonitorBuildConfig common propertiesinternal val debugMode: Boolean,internal val versionNameInvoker: () -> String,internal val logger: Logger, //koom的Loggerinternal val log: Log, //koom的Log// toolboxinternal val loadSoInvoker: (String) -> Unit, //加載sointernal val executorServiceInvoker: (() -> ExecutorService)?,//線程池// For LooperMonitorinternal val loopHandlerInvoker: () -> Handler//后臺線程handler ) {class Builder {private lateinit var mApplication: Applicationprivate var mDebugMode = trueprivate lateinit var mVersionNameInvoker: () -> Stringprivate lateinit var mDeviceIdInvoker: (() -> String)private var mRootFileInvoker: ((String) -> File)? = nullprivate var mSharedPreferencesInvoker: ((String) -> SharedPreferences)? = nullprivate var mSharedPreferencesKeysInvoker: ((SharedPreferences) -> Set<String>)? = nullprivate var mLogger: Logger? = nullprivate var mLog: Log? = nullprivate var mLoadSoInvoker: ((String) -> Unit)? = nullprivate var mExecutorServiceInvoker: (() -> ExecutorService)? = nullprivate var mLoopHandlerInvoker: (() -> Handler)? = nullfun setApplication(application: Application) = apply {mApplication = application}fun setDebugMode(debugMode: Boolean) = apply {mDebugMode = debugMode}fun setVersionNameInvoker(versionNameInvoker: () -> String) = apply {mVersionNameInvoker = versionNameInvoker}fun setRootFileInvoker(rootFileInvoker: (String) -> File) = apply {mRootFileInvoker = rootFileInvoker}fun setSharedPreferencesInvoker(sharedPreferencesInvoker: (String) -> SharedPreferences) = apply {mSharedPreferencesInvoker = sharedPreferencesInvoker}fun setSharedPreferencesKeysInvoker(sharedPreferencesKeysInvoker: (SharedPreferences) -> Set<String>) = apply {mSharedPreferencesKeysInvoker = sharedPreferencesKeysInvoker}fun setLoadSoInvoker(LoadSoInvoker: (String) -> Unit) = apply {mLoadSoInvoker = LoadSoInvoker}fun setLogger(logger: Logger) = apply {mLogger = logger}fun setLog(log: Log) = apply {mLog = log}fun setExecutorServiceInvoker(executorServiceInvoker: () -> ExecutorService) = apply {mExecutorServiceInvoker = executorServiceInvoker}fun setLoopHandlerInvoker(loopHandlerInvoker: () -> Handler) = apply {mLoopHandlerInvoker = loopHandlerInvoker}fun build(): CommonConfig = CommonConfig(application = mApplication,debugMode = mDebugMode,versionNameInvoker = mVersionNameInvoker,rootFileInvoker = mRootFileInvoker ?: {//默認(rèn)文件夾//https://blog.csdn.net/Kelaker/article/details/80471352//內(nèi)部存儲:應(yīng)用文件目錄:$applicationDir/files//外部存儲:應(yīng)用文件目錄:$applicationDir/files,// 通過Context.getExternalFilesDir(String type),type為空字符串時(shí)獲取。val rootDir = runCatching { mApplication.getExternalFilesDir("") }.getOrNull()//rootDir不為null了,則parent為rootDir,否則為mApplication.filesDirFile(rootDir ?: mApplication.filesDir, "performance/$it")//這里 todo $it是啥.apply { mkdirs() }},sharedPreferencesInvoker = mSharedPreferencesInvoker ?: {mApplication.getSharedPreferences("performance", Context.MODE_PRIVATE)//默認(rèn)performance},sharedPreferencesKeysInvoker = mSharedPreferencesKeysInvoker ?: { it.all.keys },logger = mLogger ?: object : Logger {},log = mLog ?: object : Log {},loadSoInvoker = mLoadSoInvoker ?: { System.loadLibrary(it) },executorServiceInvoker = mExecutorServiceInvoker,loopHandlerInvoker = mLoopHandlerInvoker ?: { LoopThread.LOOP_HANDLER }//默認(rèn)LoopThread.LOOP_HANDLER)} }

4.Monitor 一個(gè)CommonConfig公共配置,一個(gè)單獨(dú)配置

abstract class Monitor<C> {//一個(gè)CommonConfig公共配置private var _commonConfig: CommonConfig? = nullprotected val commonConfig: CommonConfigget() = _commonConfig!!//一個(gè)c,單獨(dú)配置private var _monitorConfig: C? = nullprotected val monitorConfig: Cget() = _monitorConfig!!//是否初始化了open var isInitialized = falseprotected inline fun throwIfNotInitialized(onDebug: () -> Unit = {throw RuntimeException("Monitor is not initialized")},onRelease: () -> Unit) {if (isInitialized) {return}if (MonitorBuildConfig.DEBUG) {onDebug()} else {onRelease()}}protected fun Boolean.syncToInitialized() = apply {isInitialized = this && isInitialized}open fun init(commonConfig: CommonConfig, monitorConfig: C) {_commonConfig = commonConfig_monitorConfig = monitorConfigisInitialized = true}open fun getLogParams(): Map<String, Any> {return mapOf("${javaClass.simpleName.decapitalize()}ingEnabled" to isInitialized)} }

5.Monitor_Application.kt

//currentActivity 當(dāng)前activity
// isForeground 是否前臺
// lifecycleEventObservers 監(jiān)聽進(jìn)程狀態(tài)
// registerActivityLifecycleCallbacks 監(jiān)聽activity狀態(tài) + 進(jìn)程狀態(tài)

//currentActivity 當(dāng)前activity // isForeground 是否前臺 // lifecycleEventObservers 監(jiān)聽進(jìn)程狀態(tài) // registerActivityLifecycleCallbacks 監(jiān)聽activity狀態(tài) + 進(jìn)程狀態(tài) private var _currentActivity: WeakReference<Activity>? = null val Application.currentActivity: Activity?get() = _currentActivity?.get()private var _isForeground = false val Application.isForegroundget() = _isForegroundprivate val _lifecycleEventObservers = CopyOnWriteArrayList<LifecycleEventObserver>() fun Application.registerProcessLifecycleObserver(observer: LifecycleEventObserver) =_lifecycleEventObservers.add(observer)fun Application.unregisterProcessLifecycleObserver(observer: LifecycleEventObserver) =_lifecycleEventObservers.remove(observer)internal fun registerApplicationExtension() {getApplication().registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {private fun updateCurrentActivityWeakRef(activity: Activity) {_currentActivity = if (_currentActivity?.get() == activity) {_currentActivity} else {WeakReference(activity)}}override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {updateCurrentActivityWeakRef(activity)}override fun onActivityStarted(activity: Activity) {}override fun onActivityResumed(activity: Activity) {updateCurrentActivityWeakRef(activity)}override fun onActivityPaused(activity: Activity) {}override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}override fun onActivityStopped(activity: Activity) {}override fun onActivityDestroyed(activity: Activity) {}})ProcessLifecycleOwner.get().lifecycle.addObserver(object : LifecycleEventObserver {override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {when (event) {Lifecycle.Event.ON_START -> _isForeground = trueLifecycle.Event.ON_STOP -> _isForeground = falseelse -> Unit}for (lifecycleEventObserver in _lifecycleEventObservers) {lifecycleEventObserver.onStateChanged(source, event)}}}) }

6.Monitor_File.kt壓縮文件,readFirstLine讀取文件第一行

/*** When compressing, only the last-level file name is retained, and the path is not retained.* Files with the same name under different paths will be overwritten* 壓縮時(shí)只保留最后一級文件名,不保留路徑。 不同路徑下的同名文件會(huì)被覆蓋*/ const val ZIP_LAST_PATH_NAME = -1/*** Keep original directory structure when compressing* 壓縮時(shí)保持原始目錄結(jié)構(gòu)*/ const val ZIP_FULL_PATH_NAME = 0fun File.zipTo(zipFile: File, zipType: Int = ZIP_LAST_PATH_NAME) {if (isFile) {arrayListOf(this).zipTo(zipFile.absolutePath, zipType)} else if (isDirectory) {//導(dǎo)入folder里的文件arrayListOf<File>().apply { buildSrcFileList(this) }.zipTo(zipFile.absolutePath, zipType)} }fun List<File>.zipTo(zipFilePath: String, zipType: Int = ZIP_LAST_PATH_NAME) {ZipOutputStream(FileOutputStream(zipFilePath)).use { out ->for (file in this) {//this指的是List<File>val filePath = file.absolutePathif (zipType == ZIP_LAST_PATH_NAME) {ZipEntry(filePath.substring(filePath.lastIndexOf("/") + 1))} else {ZipEntry(filePath)}.also {//it知道是ZipEntryout.putNextEntry(it)}//out是ZipOutputStreamFileInputStream(file).use { it.copyTo(out) }}} }fun File.readFirstLine(): String? {useLines { return it.firstOrNull() } }//遍歷文件夾將文件加入到srcFileList里 private fun File.buildSrcFileList(srcFileList: MutableList<File>) {for (file in listFiles().orEmpty()) {if (file.isDirectory) {file.buildSrcFileList(srcFileList)} else if (file.isFile) {srcFileList.add(file)}} }

7.Monitor_Process.kt 是否主進(jìn)程,進(jìn)程名,是否arm64

enum class Abi {ARMEABI_V7A,ARM64_V8A,UNKNOWN }@Volatile private var mCurrentAbi: Abi = Abi.UNKNOWN private var mProcessName: String? = nullfun isMainProcess() = MonitorManager.getApplication().packageName == getProcessName()fun getProcessName(): String? {return mProcessName?: getProcessNameByAms()?.also { mProcessName = it }?: getProcessNameByProc()?.also { mProcessName = it } }fun isArm64(): Boolean {return getCurrentAbi() == Abi.ARM64_V8A }fun getCurrentAbi(): Abi {if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return Abi.ARMEABI_V7Aif (mCurrentAbi != Abi.UNKNOWN) return mCurrentAbi// Check system api"dalvik.system.VMRuntime".toClass()//todo?.callStaticMethod<Any>("getRuntime")?.run { callMethod<Boolean>("is64Bit") }?.also {mCurrentAbi = if (it) Abi.ARM64_V8A else Abi.ARMEABI_V7Areturn mCurrentAbi}// Check address size"sun.misc.Unsafe".toClass()//todo?.callStaticMethod<Any>("getUnsafe")?.run { callMethod<Int>("addressSize") }?.also {mCurrentAbi = if (it == 8) Abi.ARM64_V8A else Abi.ARMEABI_V7Areturn mCurrentAbi}// Check so pathtry {getApplication().applicationInfo.nativeLibraryDir.contains("arm64").also { mCurrentAbi = if (it) Abi.ARM64_V8A else Abi.ARMEABI_V7A }} catch (e: Throwable) {e.printStackTrace()}return mCurrentAbi }private fun getProcessNameByProc(): String? {return try {File("/proc/" + Process.myPid() + "/" + "cmdline").readText().trim(' ', '\u0000')} catch (e: Exception) {e.printStackTrace()null} }private fun getProcessNameByAms(): String? {try {val activityManager = MonitorManager.getApplication().getSystemService(Context.ACTIVITY_SERVICE)as ActivityManagerval appProcessList = activityManager.runningAppProcessesfor (processInfo in appProcessList.orEmpty()) {if (processInfo.pid == Process.myPid()) {return processInfo.processName}}} catch (e: Exception) {e.printStackTrace()}return null }

8.Monitor_Reflect.kt 反射獲取或者設(shè)置類的靜態(tài)/非靜態(tài)成員變量,調(diào)用靜態(tài)/非靜態(tài)成員方法

fun String.toClass(): Class<*>? {return runCatching { Class.forName(this) }.getOrNull() }fun <T> Class<*>.getStaticFiledValue(filedName: String): T? {return runCatching {return@runCatching getFiledQuietly(filedName)?.get(null) as T?}.getOrNull() }fun <T> Any.getFiledValue(filedName: String): T? {return runCatching {return@runCatching this::class.java.getFiledQuietly(filedName)?.get(this) as T?}.getOrNull() }fun Class<*>.setStaticFiledValue(filedName: String, filedValue: Any?) {runCatching {return@runCatching getFiledQuietly(filedName)?.set(null, filedValue)} }fun Any.setFiledValue(filedName: String, filedValue: Any?) {runCatching {return@runCatching this::class.java.getFiledQuietly(filedName)?.set(this, filedValue)} }fun Class<*>.getFiledQuietly(filedName: String): Field? {return runCatching {var targetClass: Class<*>? = thiswhile (targetClass != Any::class.java) {//targetField是Field類型val targetField = runCatching { targetClass?.getDeclaredField(filedName) }.getOrNull()if (targetField != null) {return@runCatching targetField.also { it.isAccessible = true }} else {targetClass = targetClass?.superclass}}return@runCatching null}.getOrNull() }fun <T> Any.callMethod(methodName: String,parameterTypes: Array<Class<*>>? = null,args: Array<Any>? = null ): T? {return runCatching {val method = this::class.java.getDeclaredMethodQuietly(methodName, parameterTypes)?: return@runCatching nullreturn@runCatching if (args == null) {method.invoke(this)} else {method.invoke(this, *args)} as T?}.getOrNull() }fun <T> Class<*>.callStaticMethod(methodName: String,parameterTypes: Array<Class<*>>? = null,args: Array<Any>? = null ): T? {return runCatching {val method = this.getDeclaredMethodQuietly(methodName, parameterTypes)?: return@runCatching nullreturn@runCatching if (args == null) {method.invoke(null)} else {method.invoke(null, *args)} as T?}.getOrNull() }fun Class<*>.getDeclaredMethodQuietly(filedName: String,parameterTypes: Array<Class<*>>? = null ): Method? {return runCatching {var targetClass: Class<*>? = thiswhile (targetClass != Any::class.java) {val targetMethod = runCatching {if (parameterTypes == null) {targetClass?.getDeclaredMethod(filedName)} else {targetClass?.getDeclaredMethod(filedName, *parameterTypes)}}.getOrNull()if (targetMethod != null) {return@runCatching targetMethod.also { it.isAccessible = true }} else {targetClass = targetClass?.superclass}}return@runCatching null}.getOrNull() }

9.Monitor_SharedPreferences.kt獲取sharedPreferences的所有key

//獲取sharedPreferences的所有key val SharedPreferences.allKeys: Set<String>get() = MonitorManager.commonConfig.sharedPreferencesKeysInvoker(this)

10.Monitor_So.kt加載so,判斷是否支持64位

private const val TAG = "MonitorSo"@Deprecated("Deprecated", ReplaceWith("loadSoQuietly(soName)")) fun loadSo(soName: String) = MonitorManager.commonConfig.loadSoInvoker(soName)//加載so fun loadSoQuietly(soName: String): Boolean = runCatching {MonitorManager.commonConfig.loadSoInvoker(soName)//soreturn@runCatching true }.onFailure {it.printStackTrace()MonitorLog.e(TAG, it.message + "\n" + Log.getStackTraceString(it)) }.getOrElse { false }//是否支持64 fun isSupportArm64(): Boolean {if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {return false}return supportedABIs().contains("arm64-v8a") }//ok private fun supportedABIs(): Array<String> {return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP&& Build.SUPPORTED_ABIS.isNotEmpty()) {Build.SUPPORTED_ABIS} else if (!Build.CPU_ABI2.isNullOrEmpty()) {//todoarrayOf(Build.CPU_ABI, Build.CPU_ABI2)} else {//todoarrayOf(Build.CPU_ABI)} }

11.Monitor_System.kt 獲取mRamTotalSize總的RAM容量,mCpuCoreCount cpu核心數(shù),mCpuMaxFreq cpu最大頻率,MemInfo內(nèi)存信息,JavaHeap堆內(nèi)存信息,ProcessStatus進(jìn)程所占內(nèi)存信息

//https://my.oschina.net/u/4592355/blog/5004330 //VSS - Virtual Set Size (用處不大)虛擬耗用內(nèi)存(包含共享庫占用的全部內(nèi)存,以及分配但未使用內(nèi)存)。 // 其大小還包括了可能不在RAM中的內(nèi)存(比如雖然malloc分配了空間,但尚未寫入)。 // VSS 很少被用于判斷一個(gè)進(jìn)程的真實(shí)內(nèi)存使用量。 //RSS - Resident Set Size (用處不大) //實(shí)際使用物理內(nèi)存(包含共享庫占用的全部內(nèi)存)。但是RSS還是可能會(huì)造成誤導(dǎo),因?yàn)樗鼉H僅表示該進(jìn)程所使用的所有共享庫的大小, // 它不管有多少個(gè)進(jìn)程使用該共享庫,該共享庫僅被加載到內(nèi)存一次。所以RSS并不能準(zhǔn)確反映單進(jìn)程的內(nèi)存占用情況。 //PSS - Proportional Set Size (僅供參考) //實(shí)際使用的物理內(nèi)存(比例分配共享庫占用的內(nèi)存,按照進(jìn)程數(shù)等比例劃分)。 //例如:如果有三個(gè)進(jìn)程都使用了一個(gè)共享庫,共占用了30頁內(nèi)存。那么PSS將認(rèn)為每個(gè)進(jìn)程分別占用該共享庫10頁的大小。 //PSS是非常有用的數(shù)據(jù),因?yàn)橄到y(tǒng)中所有進(jìn)程的PSS都相加的話,就剛好反映了系統(tǒng)中的 總共占用的內(nèi)存。 // 而當(dāng)一個(gè)進(jìn)程被銷毀之后, 其占用的共享庫那部分比例的PSS,將會(huì)再次按比例分配給余下使用該庫的進(jìn)程。 //這樣PSS可能會(huì)造成一點(diǎn)的誤導(dǎo),因?yàn)楫?dāng)一個(gè)進(jìn)程被銷毀后, PSS不能準(zhǔn)確地表示返回給全局系統(tǒng)的內(nèi)存。 //USS - Unique Set Size (非常有用) //進(jìn)程獨(dú)自占用的物理內(nèi)存(不包含共享庫占用的內(nèi)存)。USS是非常非常有用的數(shù)據(jù),因?yàn)樗从沉诉\(yùn)行一個(gè)特定進(jìn)程真實(shí)的邊際成本 // (增量成本)。當(dāng)一個(gè)進(jìn)程被銷毀后,USS是真實(shí)返回給系統(tǒng)的內(nèi)存。當(dāng)進(jìn)程中存在一個(gè)可疑的內(nèi)存泄露時(shí),USS是最佳觀察數(shù)據(jù)。private val VSS_REGEX = "VmSize:\\s*(\\d+)\\s*kB".toRegex()//todo private val RSS_REGEX = "VmRSS:\\s*(\\d+)\\s*kB".toRegex()//todo private val THREADS_REGEX = "Threads:\\s*(\\d+)\\s*".toRegex()private val MEM_TOTAL_REGEX = "MemTotal:\\s*(\\d+)\\s*kB".toRegex() private val MEM_FREE_REGEX = "MemFree:\\s*(\\d+)\\s*kB".toRegex() private val MEM_AVA_REGEX = "MemAvailable:\\s*(\\d+)\\s*kB".toRegex() //https://www.jianshu.com/p/9edfe9d5eb34 //ion disp:display 相關(guān)的ion模塊內(nèi)存占用 ion是離子 todo //cma usage:cma模塊占用 private val MEM_CMA_REGEX = "CmaTotal:\\s*(\\d+)\\s*kB".toRegex()//todo private val MEM_ION_REGEX = "ION_heap:\\s*(\\d+)\\s*kB".toRegex()//todoprivate var mCpuCoreCount: Int? = null private var mRamTotalSize: Long? = null private var mCpuMaxFreq: Double? = null@JvmField var lastProcessStatus = ProcessStatus()@JvmField var lastMemInfo = MemInfo()@JvmField var lastJavaHeap = JavaHeap()fun getRamTotalSize(): Long {return mRamTotalSize ?: File("/proc/meminfo").useLines {it.forEach { line ->if (line.contains("MemTotal")) {val array = line.split("\\s+".toRegex()).toTypedArray()return@useLines array.getOrElse(1) { "0" }.toLong() shl 10}}return@useLines 0L}.also { mRamTotalSize = it } }fun getRamAvailableSize(context: Context): Long {val memoryInfo = ActivityManager.MemoryInfo()(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).also { it.getMemoryInfo(memoryInfo) }return memoryInfo.availMem }fun getCpuCoreCount(): Int {return mCpuCoreCount?: runCatching {File("/sys/devices/system/cpu/").listFiles { pathname -> Pattern.matches("cpu[0-9]+", pathname.name) }?.size?: 0}.getOrDefault(Runtime.getRuntime().availableProcessors()).also { mCpuCoreCount = it } }fun getCpuMaxFreq(): Double {return mCpuMaxFreq?: runCatching {(File("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq").readFirstLine()?.trim()?.toDouble()?: 0.0) / 1000}.getOrDefault(0.0).also { mCpuMaxFreq = it } }/*** Get Pss/Vss/etc.*/ fun getProcessStatus(): ProcessStatus {val processStatus = ProcessStatus()runCatching {File("/proc/self/status").useLines {it.forEach { line ->//讀取文件的每行//如果都不為0的時(shí)候返回信息if (processStatus.vssKbSize != 0L && processStatus.rssKbSize != 0L&& processStatus.threadsCount != 0L) {lastProcessStatus = processStatusreturn processStatus}when {line.startsWith("VmSize") -> processStatus.vssKbSize = VSS_REGEX.matchValue(line)line.startsWith("VmRSS") -> processStatus.rssKbSize = RSS_REGEX.matchValue(line)line.startsWith("Threads") ->processStatus.threadsCount = THREADS_REGEX.matchValue(line)}}}}lastProcessStatus = processStatusreturn processStatus }fun getMemoryInfo(): MemInfo {val memInfo = MemInfo()File("/proc/meminfo").useLines {it.forEach { line ->when {line.startsWith("MemTotal") -> memInfo.totalInKb = MEM_TOTAL_REGEX.matchValue(line)line.startsWith("MemFree") -> memInfo.freeInKb = MEM_FREE_REGEX.matchValue(line)line.startsWith("MemAvailable") -> memInfo.availableInKb = MEM_AVA_REGEX.matchValue(line)line.startsWith("CmaTotal") -> memInfo.cmaTotal = MEM_CMA_REGEX.matchValue(line)line.startsWith("ION_heap") -> memInfo.IONHeap = MEM_ION_REGEX.matchValue(line)}}}memInfo.rate = 1.0f * memInfo.availableInKb / memInfo.totalInKblastMemInfo = memInforeturn memInfo }fun getJavaHeap(): JavaHeap {val javaHeap = JavaHeap()javaHeap.max = Runtime.getRuntime().maxMemory()javaHeap.total = Runtime.getRuntime().totalMemory()javaHeap.free = Runtime.getRuntime().freeMemory()javaHeap.used = javaHeap.total - javaHeap.freejavaHeap.rate = 1.0f * javaHeap.used / javaHeap.maxlastJavaHeap = javaHeapreturn javaHeap }class ProcessStatus {@JvmFieldvar vssKbSize: Long = 0@JvmFieldvar rssKbSize: Long = 0@JvmFieldvar threadsCount: Long = 0 }class MemInfo(@JvmFieldvar totalInKb: Long = 0,@JvmFieldvar freeInKb: Long = 0,@JvmFieldvar availableInKb: Long = 0,@JvmFieldvar IONHeap: Long = 0,//todo@JvmFieldvar cmaTotal: Long = 0,//todo@JvmFieldvar rate: Float = 0f )//https://blog.csdn.net/qijingwang/article/details/86162648 //JvmField在這里是生成get set方法,在伴生對象里,用于消除調(diào)用Companion class JavaHeap(@JvmFieldvar max: Long = 0,@JvmFieldvar total: Long = 0,@JvmFieldvar free: Long = 0,@JvmFieldvar used: Long = 0,@JvmFieldvar rate: Float = 0f )private fun Regex.matchValue(s: String) = matchEntire(s.trim())?.groupValues?.getOrNull(1)?.toLong() ?: 0L

12.Monitor_Thread.kt 在主線程/線程池里執(zhí)行代碼

internal val mainHandler = Handler(Looper.getMainLooper())//異步 fun async(delayMills: Long = 0L, block: () -> Unit) {if (delayMills != 0L) {mainHandler.postDelayed({MonitorManager.commonConfig.executorServiceInvoker?.invoke()?.submit(block)?: thread { block() }}, delayMills)} else {//調(diào)用線程池運(yùn)行block,如果為空則創(chuàng)建thread創(chuàng)建blockMonitorManager.commonConfig.executorServiceInvoker?.invoke()?.submit(block)?: thread { block() }} }fun postOnMainThread(delayMills: Long = 0L, block: () -> Unit) {mainHandler.postDelayed(block, delayMills) }fun runOnMainThread(block: () -> Unit) {if (Looper.myLooper() == Looper.getMainLooper()) {block()} else {mainHandler.post(block)} }fun postOnMainThread(delay: Long = 0L, runnable: Runnable) {mainHandler.postDelayed(runnable, delay) }fun removeCallbacks(runnable: Runnable) {mainHandler.removeCallbacks(runnable) }

13.MonitorBuildConfig 獲取一些信息debug,version_name,rom

object MonitorBuildConfig {@JvmStaticval DEBUG by lazy { MonitorManager.commonConfig.debugMode }@JvmStaticval VERSION_NAME by lazy { MonitorManager.commonConfig.versionNameInvoker() }@JvmStaticval ROM by lazy { Build.MANUFACTURER.toUpperCase().let { if (it == "HUAWEI") "EMUI" else "OTHER"} } }

14.MonitorConfig 里邊有個(gè)builder,生成相應(yīng)的MonitorConfig

abstract class MonitorConfig<M> {interface Builder<C: MonitorConfig<*>> {fun build(): C} }

15.MonitorLog 本地打log

//MonitorLog本地打log object MonitorLog {//https://blog.csdn.net/qq_33404903/article/details/89425671// JvmStatic指定如果它是函數(shù),則需要從此元素生成額外的靜態(tài)方法。// 如果此元素是屬性,則應(yīng)生成額外的靜態(tài) getter / setter 方法。@JvmStaticfun v(tag: String, msg: String): Int {return MonitorManager.commonConfig.log.v(tag, msg)}@JvmStaticfun i(tag: String, msg: String): Int {return MonitorManager.commonConfig.log.i(tag, msg)}@JvmStaticfun d(tag: String, msg: String): Int {return MonitorManager.commonConfig.log.d(tag, msg)}@JvmStaticfun w(tag: String, msg: String): Int {return MonitorManager.commonConfig.log.w(tag, msg)}@JvmStaticfun e(tag: String, msg: String): Int {return MonitorManager.commonConfig.log.e(tag, msg)}@JvmStaticfun v(tag: String, msg: String, syncToLogger: Boolean): Int {if (syncToLogger) MonitorLogger.addCustomStatEvent(tag, msg)return this.v(tag, msg)}@JvmStaticfun i(tag: String, msg: String, syncToLogger: Boolean): Int {if (syncToLogger) MonitorLogger.addCustomStatEvent(tag, msg)return this.i(tag, msg)}@JvmStaticfun d(tag: String, msg: String, syncToLogger: Boolean): Int {if (syncToLogger) MonitorLogger.addCustomStatEvent(tag, msg)return this.d(tag, msg)}@JvmStaticfun w(tag: String, msg: String, syncToLogger: Boolean): Int {if (syncToLogger) MonitorLogger.addCustomStatEvent(tag, msg)return this.w(tag, msg)}@JvmStaticfun e(tag: String, msg: String, syncToLogger: Boolean): Int {if (syncToLogger) MonitorLogger.addCustomStatEvent(tag, msg)return this.e(tag, msg)} }interface Log {fun v(tag: String, msg: String) = runIfDebug { android.util.Log.v(tag, msg) }fun i(tag: String, msg: String) = runIfDebug { android.util.Log.i(tag, msg) }fun d(tag: String, msg: String) = runIfDebug { android.util.Log.d(tag, msg) }fun w(tag: String, msg: String) = runIfDebug { android.util.Log.w(tag, msg) }fun e(tag: String, msg: String) = runIfDebug { android.util.Log.e(tag, msg) } }internal inline fun runIfDebug(block: () -> Int): Int {if (MonitorBuildConfig.DEBUG) {return block()}return -1 }

16.MonitorLogger收集log,埋點(diǎn)

//收集log,埋點(diǎn) object MonitorLogger : Logger {override fun addCustomStatEvent(key: String, value: String?, realtimeReport: Boolean) {MonitorManager.commonConfig.logger.addCustomStatEvent(key, value, realtimeReport)}override fun addExceptionEvent(message: String, crashType: Int) {MonitorManager.commonConfig.logger.addExceptionEvent(message, crashType)} }interface Logger {fun addCustomStatEvent(key: String, value: String?, realtimeReport: Boolean = false) = Unitfun addExceptionEvent(message: String, @ExceptionType crashType: Int) = Unit@IntDef(ExceptionType.UNKNOWN_TYPE,ExceptionType.OOM,ExceptionType.OOM_STACKS,ExceptionType.NATIVE_LEAK,ExceptionType.THREAD_STACKS)@Retention(AnnotationRetention.SOURCE)annotation class ExceptionType {companion object {const val UNKNOWN_TYPE = 0const val OOM = 1const val OOM_STACKS = 2const val NATIVE_LEAK = 3const val THREAD_STACKS = 4}} }

17.MonitorManager保存Monitor即配置的map

object MonitorManager {internal val MONITOR_MAP = ConcurrentHashMap<Class<*>, Monitor<*>>()internal lateinit var commonConfig: CommonConfig@JvmStaticfun initCommonConfig(commonConfig: CommonConfig) = apply {this.commonConfig = commonConfig}//todo@JvmStaticfun <M : MonitorConfig<*>> addMonitorConfig(config: M) = apply {var supperType: Type? = config.javaClass.genericSuperclasswhile (supperType is Class<*>) {supperType = supperType.genericSuperclass//`getGenericSuperclass` 會(huì)包含該超類的泛型。}//ParameterizedType參數(shù)化類型if (supperType !is ParameterizedType) {throw java.lang.RuntimeException("config must be parameterized")}//取出指定的泛型。val monitorType = supperType.actualTypeArguments[0] as Class<Monitor<M>>if (MONITOR_MAP.containsKey(monitorType)) {return@apply}val monitor = try {monitorType.getDeclaredField("INSTANCE").get(null) as Monitor<M>} catch (e: Throwable) {monitorType.newInstance() as Monitor<M>}MONITOR_MAP[monitorType] = monitormonitor.init(commonConfig, config)monitor.logMonitorEvent()}@JvmStaticfun getApplication() = commonConfig.application@Deprecated("Use Monitor Directly")@JvmStaticfun <M : Monitor<*>> getMonitor(clazz: Class<M>): M {return MONITOR_MAP[clazz] as M}@Deprecated("Use Monitor#isInitialized Directly")@JvmStaticfun <M : Monitor<*>> isInitialized(clazz: Class<M>): Boolean {return MONITOR_MAP[clazz] != null}@JvmStaticfun onApplicationCreate() {registerApplicationExtension()registerMonitorEventObserver()}//onStateChanged ON_START的時(shí)候打印MONITOR_MAP的信息private fun registerMonitorEventObserver() {ProcessLifecycleOwner.get().lifecycle.addObserver(object : LifecycleEventObserver {private var mHasLogMonitorEvent = falseoverride fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {if (event == Lifecycle.Event.ON_START) {logAllMonitorEvent()}}private fun logAllMonitorEvent() {if (mHasLogMonitorEvent) returnmHasLogMonitorEvent = truemutableMapOf<Any?, Any?>().apply { MONITOR_MAP.forEach { putAll(it.value.getLogParams()) } }//also函數(shù)的結(jié)構(gòu)實(shí)際上和let很像唯一的區(qū)別就是返回值的不一樣,let是以閉包的形式返回,// 返回函數(shù)體內(nèi)最后一行的值,如果最后一行為空就返回一個(gè)Unit類型的默認(rèn)值。// 而also函數(shù)返回的則是傳入對象的本身.also {MonitorLogger.addCustomStatEvent("switch-stat", JSONObject(it).toString())}}})}private fun <C> Monitor<C>.logMonitorEvent() {if (!getApplication().isForeground) returnmutableMapOf<Any?, Any?>().apply { putAll(this@logMonitorEvent.getLogParams()) }// todo 什么語法.also {MonitorLogger.addCustomStatEvent("switch-stat", JSONObject(it).toString())}} }

總結(jié)

以上是生活随笔為你收集整理的koom 源码分析之 koom-monitor-base的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。