[6.2.6][技术优化] 将卡顿日志转成在链路日志中存储
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user