[6.2.6][技术优化] 将卡顿日志转成在链路日志中存储

This commit is contained in:
renwj
2023-12-22 17:42:33 +08:00
parent 5256f4597f
commit acdcde8caf
5 changed files with 41 additions and 217 deletions

View File

@@ -1,142 +0,0 @@
package com.mogo.launcher.lancet
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.view.View
import androidx.annotation.*
import androidx.core.view.ViewCompat
import androidx.fragment.app.*
import androidx.lifecycle.*
import androidx.lifecycle.Lifecycle.Event
import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
import com.knightboost.lancet.api.*
import com.knightboost.lancet.api.Scope.LEAF
import com.knightboost.lancet.api.annotations.*
import com.knightboost.lancet.api.annotations.Weaver
import com.mogo.eagle.core.utilcode.kotlin.*
import io.netty.util.internal.ConcurrentSet
import java.lang.ref.*
import java.lang.reflect.Modifier
import java.util.concurrent.ConcurrentHashMap
@Keep
@Weaver
@Group("memory_leak")
class MemoryLeakFix {
@NameRegex("(com\\.zhidao|com\\.elegant|com\\.zhidaoauto|com\\.zhjt|com\\.mogo(?!(\\.thread\\.ext|\\.launcher\\.lancet))).*")
@Insert(mayCreateSuper = true)
@ImplementedInterface("java.lang.Runnable", scope = LEAF)
@TargetMethod(methodName = "run")
fun runProxy() {
if (AccessSyntheticUtils.isTargetAlive(This.get())) {
Origin.callVoid()
}
}
}
internal class AccessSyntheticUtils {
companion object {
private val fields = ConcurrentHashMap<String, WeakReference<Any>>()
private val observers = ConcurrentSet<String>()
// true: 代表要执行原来的run方法体
// false: 代表不执行原来的run方法体
@JvmStatic
fun isTargetAlive(obj: Any): Boolean {
try {
val clazz = obj.javaClass
if (!clazz.isAnonymousClass) {
return true
}
val key = clazz.name
return (fields[key] ?: clazz.declaredFields.find {
it.isSynthetic &&
((it.modifiers and Modifier.STATIC) == 0) &&
(View::class.java.isAssignableFrom(it.type) or
Context::class.java.isAssignableFrom(it.type) or
Fragment::class.java.isAssignableFrom(it.type) or
android.app.Fragment::class.java.isAssignableFrom(it.type) or
Dialog::class.java.isAssignableFrom(it.type)
)
}?.let {
it.isAccessible = true
val wf = WeakReference(it.get(obj), ReferenceQueue())
fields[key] = wf
wf
})?.also {
if (it.isEnqueued) {
//对像被垃圾回收了
fields.remove(key)
}
}?.get()?.let { t ->
var lifecycle: Lifecycle? = null
val ret = when (t) {
is View -> {
lifecycle = t.lifecycleOwner.lifecycle
t.parent == null || ViewCompat.isAttachedToWindow(t)
}
is Activity -> {
lifecycle = t.findViewById<View>(android.R.id.content)?.lifecycleOwner?.lifecycle
!t.isFinishing && !t.isDestroyed
}
is Fragment -> {
lifecycle = t.lifecycle
!t.isDetached
}
is android.app.Fragment -> {
lifecycle = t.view?.lifecycleOwner?.lifecycle
!t.isDetached
}
is Dialog -> {
t.window?.decorView?.let {
v ->
lifecycle = v.lifecycleOwner.lifecycle
ViewCompat.isAttachedToWindow(v)
} ?: false
}
else -> {
true
}
}
if (!ret) {
assignFinalFieldNull(obj, t.javaClass)
} else {
val l = lifecycle
if (l != null && !observers.contains(key)) {
observers.add(key)
l.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Event) {
if (event == ON_DESTROY) {
assignFinalFieldNull(obj, t.javaClass)
observers.remove(key)
}
}
})
}
}
ret
} ?: true
} catch (ignore: Throwable) { }
return true
}
@JvmStatic
private fun assignFinalFieldNull(obj: Any, fieldType: Class<*>) {
try {
obj.javaClass.declaredFields.find {
it.isSynthetic &&
((it.modifiers and Modifier.STATIC) == 0) && it.type == fieldType
}?.also {
it.isAccessible = true
it.set(obj, null)
}
} catch (t: Throwable) {
t.printStackTrace()
}
}
}
}