[6.2.6][技术优化] 将卡顿日志转成在链路日志中存储
This commit is contained in:
@@ -5,11 +5,12 @@ import android.os.SystemClock;
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.mogo.core.lancetx.compiler.lib.generator.Type;
|
||||
import com.mogo.core.lancetx.compiler.lib.hook.IHookInvoker;
|
||||
import com.mogo.eagle.core.data.deva.chain.ChainConstant;
|
||||
import com.mogo.eagle.core.function.api.devatools.block.IMoGoBlockProvider;
|
||||
import com.mogo.eagle.core.function.api.devatools.perf.IMoGoCpuUsageProvider;
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager;
|
||||
import com.mogo.eagle.core.function.main.ARouterUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.VLogUtils;
|
||||
import com.zhjt.service.chain.ChainLog;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
@@ -170,8 +171,8 @@ public class HookInvokerImpl implements IHookInvoker {
|
||||
String s = builder.toString();
|
||||
|
||||
|
||||
VLogUtils.w("HookHandler", "Junk Detected:" + builder, 4096);
|
||||
// linkedLog(type, builder.toString());
|
||||
//VLogUtils.w("HookHandler", "Junk Detected:" + builder, 4096);
|
||||
linkedLog(type, builder.toString());
|
||||
if (flag) {
|
||||
extra.setLength(0);
|
||||
}
|
||||
@@ -248,7 +249,7 @@ public class HookInvokerImpl implements IHookInvoker {
|
||||
}
|
||||
if (holder != null) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append("##holder::").append(holder);
|
||||
sb.append("##holder::").append(holder.getName());
|
||||
} else {
|
||||
sb.append("holder::").append(holder);
|
||||
}
|
||||
@@ -287,19 +288,19 @@ public class HookInvokerImpl implements IHookInvoker {
|
||||
}
|
||||
}
|
||||
|
||||
// private void linkedLog(Type type, String msg) {
|
||||
// try {
|
||||
// linkedLogInternal(type,msg);
|
||||
// } catch (Throwable t) {
|
||||
// t.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @ChainLog(
|
||||
// linkChainLog = ChainConstant.CHAIN_TYPE_ANR_LEAK,
|
||||
// linkCode = ChainConstant.CHAIN_SOURCE_HMI,
|
||||
// nodeAliasCode = ChainConstant.CHAIN_CODE_MAIN_BLOCK,
|
||||
// paramIndexes = { 0, 1 }
|
||||
// )
|
||||
// private void linkedLogInternal(Type type, String msg) {}
|
||||
private void linkedLog(Type type, String msg) {
|
||||
try {
|
||||
linkedLogInternal(type,msg);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@ChainLog(
|
||||
linkChainLog = ChainConstant.CHAIN_TYPE_ANR_LEAK,
|
||||
linkCode = ChainConstant.CHAIN_SOURCE_HMI,
|
||||
nodeAliasCode = ChainConstant.CHAIN_CODE_MAIN_BLOCK,
|
||||
paramIndexes = { 0, 1 }
|
||||
)
|
||||
private void linkedLogInternal(Type type, String msg) {}
|
||||
}
|
||||
|
||||
@@ -9,40 +9,21 @@ import com.knightboost.lancet.api.annotations.TargetClass
|
||||
import com.knightboost.lancet.api.annotations.TargetMethod
|
||||
import com.knightboost.lancet.api.annotations.Weaver
|
||||
import com.mogo.eagle.core.block.runtime.message.Message
|
||||
import com.mogo.eagle.core.block.runtime.utils.TimeUtils.Companion.now
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@Weaver
|
||||
@Group("main_block_check")
|
||||
class UiPostLancet {
|
||||
|
||||
|
||||
internal data class ActionWrapper(var action: Runnable): Runnable {
|
||||
|
||||
override fun run() {
|
||||
val start = now()
|
||||
try {
|
||||
action.run()
|
||||
} finally {
|
||||
CallerDevaToolsManager.block()?.takeIf {
|
||||
it.hasInit()
|
||||
}?.recorder()?.recycle(Message.acquire(handler = null, action = action, duration = now() - start))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val map by lazy { ConcurrentHashMap<Runnable, ActionWrapper>() }
|
||||
|
||||
@JvmStatic
|
||||
@TargetClass(value = "android.app.Activity", scope = Scope.ALL)
|
||||
@TargetMethod(methodName = "runOnUiThread")
|
||||
@ReplaceInvoke
|
||||
fun runOnUiThreadOfActivity(activity: Activity, action: Runnable) {
|
||||
try {
|
||||
activity.runOnUiThread(ActionWrapper(action).also { map[action] = it })
|
||||
activity.runOnUiThread(action)
|
||||
} finally {
|
||||
CallerDevaToolsManager.block()?.takeIf {
|
||||
it.hasInit()
|
||||
@@ -55,22 +36,8 @@ class UiPostLancet {
|
||||
@TargetMethod(methodName = "post")
|
||||
@ReplaceInvoke
|
||||
fun post(view: View, action: Runnable): Boolean {
|
||||
return try {
|
||||
view.post(ActionWrapper(action).also { map[action] = it })
|
||||
} finally {
|
||||
CallerDevaToolsManager.block()?.takeIf {
|
||||
it.hasInit()
|
||||
}?.recorder()?.insert(Message.acquire(handler = null, action = action, extra = mapOf(view.javaClass.name to "post")))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@TargetClass(value = "android.view.View", scope = Scope.ALL)
|
||||
@TargetMethod(methodName = "postDelayed")
|
||||
@ReplaceInvoke
|
||||
fun postDelayed(view: View, action: Runnable, delayMillis: Long): Boolean {
|
||||
return try {
|
||||
view.postDelayed(ActionWrapper(action).also { map[action] = it }, delayMillis)
|
||||
view.post(action)
|
||||
} finally {
|
||||
CallerDevaToolsManager.block()?.takeIf {
|
||||
it.hasInit()
|
||||
@@ -78,20 +45,32 @@ class UiPostLancet {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@TargetClass(value = "android.view.View", scope = Scope.ALL)
|
||||
@TargetMethod(methodName = "postDelayed")
|
||||
@ReplaceInvoke
|
||||
fun postDelayed(view: View, action: Runnable, delayMillis: Long): Boolean {
|
||||
return try {
|
||||
view.postDelayed(action, delayMillis)
|
||||
} finally {
|
||||
CallerDevaToolsManager.block()?.takeIf {
|
||||
it.hasInit()
|
||||
}?.recorder()?.insert(Message.acquire(handler = null, action = action, delay = delayMillis, extra = mapOf(view.javaClass.name to "postDelayed")))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@TargetClass(value = "android.view.View", scope = Scope.ALL)
|
||||
@TargetMethod(methodName = "removeCallbacks")
|
||||
@ReplaceInvoke
|
||||
fun removeCallbacks(view: View, action: Runnable): Boolean {
|
||||
return try {
|
||||
view.removeCallbacks(map.remove(action))
|
||||
view.removeCallbacks(action)
|
||||
} finally {
|
||||
CallerDevaToolsManager.block()?.takeIf {
|
||||
it.hasInit()
|
||||
}?.recorder()?.remove(Message.acquire(handler = null, action = action, extra = mapOf(view.javaClass.name to "removeCallbacks")))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,27 +13,22 @@ import com.mogo.eagle.core.block.runtime.report.*
|
||||
import com.mogo.eagle.core.function.api.devatools.block.*
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
|
||||
import com.mogo.eagle.core.utilcode.util.GsonUtils
|
||||
import com.mogo.eagle.core.utilcode.util.VLogUtils
|
||||
import java.util.concurrent.TimeUnit.SECONDS
|
||||
|
||||
internal class MoGoBlockProviderImpl: IMoGoBlockProvider, IBlockListener {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "BLOCK_REPORT"
|
||||
}
|
||||
|
||||
@Volatile
|
||||
private var hasInit = false
|
||||
|
||||
// private val linkedLog by lazy { MainBlockLinkedLog() }
|
||||
private val linkedLog by lazy { MainBlockLinkedLog() }
|
||||
|
||||
override fun init(ctx: Context) {
|
||||
BlockDetector.init(BlockMetrics.Builder()
|
||||
.context(ctx)
|
||||
.multiplier(1.2f)
|
||||
.multiplier(2.0f)
|
||||
.isDebug(false)
|
||||
.period(5, SECONDS)
|
||||
.junkRateThreshold(0.2f)
|
||||
.junkRateThreshold(0.6f)
|
||||
.recorder(null, 500, 500)
|
||||
.build())
|
||||
hasInit = true
|
||||
@@ -69,12 +64,7 @@ internal class MoGoBlockProviderImpl: IMoGoBlockProvider, IBlockListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
val msg = GsonUtils.toJson(map)
|
||||
try {
|
||||
VLogUtils.w(TAG, msg)
|
||||
} catch (t: Throwable) {
|
||||
Log.e(TAG, "onDumped error", t)
|
||||
}
|
||||
linkedLog.record(GsonUtils.toJson(map))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,13 +14,9 @@ LancetX {
|
||||
]
|
||||
}
|
||||
weaveGroup {
|
||||
|
||||
crash_fix {
|
||||
enable true
|
||||
}
|
||||
memory_leak {
|
||||
enable true
|
||||
}
|
||||
textview_opt {
|
||||
enable true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user