Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加look命令,用来观测方法内的本地变量表,可以通过行号或者特殊Code(jad -L 来输出)来指定位置 #2435

Closed
wants to merge 4 commits into from

Conversation

isadliliying
Copy link

为什么要做这个呢?

  • 协助快速定位排查数据问题,打日志看的话有时候会出现需要多次重复打的情况
  • 有看到isuues里边也有一些小伙伴提到这个

为什么要定义新的命令?

  • 跟观测非常契合的命令是watch,但是watch的对象是method,而我们观测local variables的时候,用来作为定位点是比较合适的(因为同一个变量会被多次重复赋值),这样会导致watchlistenerkey跟根据参数而有所差异,在处理注册监听时会比较麻烦
  • 独立一个命令也能降低对旧命令的影响

实现思路:

  • 定义新的Advice变量 varMap,类型是HashMap,key是变量名,value是变量值
  • 插桩的位置是命令参数传入的 行号 或 特殊Code 之前,并使用-1来表示方法退出前的插桩点
  • 监听器的注册等也作了相应的区分处理

已经做的基本测试:

  • 基础功能实现,能观测到定义的local variables,并能在condition-express中使用
  • 重复插桩处理,增加了对应的LocationFilter,避免重复插桩
  • 多监听的兼容支持
  • tracewatch命令的同时使用的兼容处理

其它:

…i-look-command

� Conflicts:
�	core/src/main/java/com/taobao/arthas/core/advisor/Enhancer.java
@CLAassistant
Copy link

CLAassistant commented Feb 24, 2023

CLA assistant check
All committers have signed the CLA.

@isadliliying
Copy link
Author

特殊Code的解释如下:

kotlin源码:

/*56*/    fun index(): JSONObject {
/*57*/        listOf(1,2,3,4,5,6).map {
/*58*/            listOf("a","b","c","d","e","f").map {
/*59*/                listOf(true,false,true,false,false).map {
/*60*/                    println(it)
/*61*/                    if (true) return JSONObject()
/*62*/                }
/*63*/            }
/*64*/        }
/*65*/        return ResponseBuilder().ok().data("Hello World!").build()
/*66*/    }

jad出来的样子:

       public final JSONObject index() {
           void var3_3;
           void $receiver$iv$iv;
           Iterable $receiver$iv;
/*57*/     Iterable iterable = $receiver$iv = (Iterable)CollectionsKt.listOf(1, 2, 3, 4, 5, 6);
           Collection destination$iv$iv = new ArrayList(CollectionsKt.collectionSizeOrDefault($receiver$iv, 10));
/*83*/     for (Object item$iv$iv : $receiver$iv$iv) {
               void $receiver$iv$iv2;
               Iterable $receiver$iv2;
               int n = ((Number)item$iv$iv).intValue();
               Collection collection = destination$iv$iv;
               boolean bl = false;
/*58*/         Iterable iterable2 = $receiver$iv2 = (Iterable)CollectionsKt.listOf("a", "b", "c", "d", "e", "f");
               Collection destination$iv$iv2 = new ArrayList(CollectionsKt.collectionSizeOrDefault($receiver$iv2, 10));
/*86*/         for (Object item$iv$iv2 : $receiver$iv$iv2) {
                   void $receiver$iv$iv3;
                   Iterable $receiver$iv3;
                   String string = (String)item$iv$iv2;
                   Collection collection2 = destination$iv$iv2;
                   boolean bl2 = false;
/*59*/             Iterable iterable3 = $receiver$iv3 = (Iterable)CollectionsKt.listOf(true, false, true, false, false);
                   Collection destination$iv$iv3 = new ArrayList(CollectionsKt.collectionSizeOrDefault($receiver$iv3, 10));
                   Iterator iterator2 = $receiver$iv$iv3.iterator();
                   if (iterator2.hasNext()) {
                       void it;
                       void it2;
                       void it3;
                       Object item$iv$iv3 = iterator2.next();
                       boolean bl3 = (Boolean)item$iv$iv3;
                       Collection collection3 = destination$iv$iv3;
                       boolean bl4 = false;
/*60*/                 System.out.println((boolean)it3);
                       JSONObject jSONObject = new JSONObject();
                       return jSONObject;
                   }
/*91*/             List list = (List)destination$iv$iv3;
                   collection2.add(list);
               }
/*92*/         List list = (List)destination$iv$iv2;
               collection.add(list);
           }
/*93*/     List cfr_ignored_0 = (List)var3_3;
           return new ResponseBuilder().ok().data((Object)"Hello World!").build();
       }

问题:
反编译后,它的行号分布是乱序的,另外实践中还发现有重复行号的问题,而且反编译后与源代码大相径庭,也生成了很多的额外的零时变量,也有很多行是没有行号的,所以使用行号定位的话,是不够完善的,有些点无法进行定位插入监听!

另外的想法:
如何能监听到所有本地变量的变化过程呢? -> 变量在何时会被改变呢? -> 赋值、作为方法参数被调用
基于此,通过筛选方法中的InsnNode,只保留 VarInsnNode 和 MethodInsnNode 作为备选插入点,然后生成类似如下的标记行并以此为变量监测的插入点. 但是感觉这样使用起来很麻烦,需要结合源码,对比行号,调用等才能找到对应的点,大佬觉得呢 @hengyunabc
目前格式如: 行号 + 标识 + 方法调用/变量赋值

/*57*/   d6e3-1   invoke-method: java.lang.Integer#valueOf:(I)Ljava/lang/Integer;
/*57*/   d6e3-2   invoke-method: java.lang.Integer#valueOf:(I)Ljava/lang/Integer;
/*57*/   d6e3-3   invoke-method: java.lang.Integer#valueOf:(I)Ljava/lang/Integer;
/*57*/   d6e3-4   invoke-method: java.lang.Integer#valueOf:(I)Ljava/lang/Integer;
/*57*/   d6e3-5   invoke-method: java.lang.Integer#valueOf:(I)Ljava/lang/Integer;
/*57*/   d6e3-6   invoke-method: java.lang.Integer#valueOf:(I)Ljava/lang/Integer;
/*57*/   395b-1   invoke-method: kotlin.collections.CollectionsKt#listOf:([Ljava/lang/Object;)Ljava/util/List;
/*82*/   0ee8-1   invoke-method: kotlin.collections.CollectionsKt#collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
/*82*/   f0bd-1   invoke-method: java.util.ArrayList#<init>:(I)V
/*83*/   7cda-1   invoke-method: java.lang.Iterable#iterator:()Ljava/util/Iterator;
/*83*/   ad72-1   invoke-method: java.util.Iterator#hasNext:()Z
/*83*/   b105-1   invoke-method: java.util.Iterator#next:()Ljava/lang/Object;
/*84*/   f9e5-1   invoke-method: java.lang.Number#intValue:()I
/*84*/   11a1-1   assign-variable: it
/*84*/   30e3-1   assign-variable: $i$a$-map-MainApplication$index$1
/*58*/   395b-2   invoke-method: kotlin.collections.CollectionsKt#listOf:([Ljava/lang/Object;)Ljava/util/List;
/*85*/   0ee8-2   invoke-method: kotlin.collections.CollectionsKt#collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
/*85*/   f0bd-2   invoke-method: java.util.ArrayList#<init>:(I)V
/*86*/   7cda-2   invoke-method: java.lang.Iterable#iterator:()Ljava/util/Iterator;
/*86*/   ad72-2   invoke-method: java.util.Iterator#hasNext:()Z
/*86*/   b105-2   invoke-method: java.util.Iterator#next:()Ljava/lang/Object;
/*87*/   a430-1   assign-variable: $i$a$-map-MainApplication$index$1$1
/*59*/   38d8-1   invoke-method: java.lang.Boolean#valueOf:(Z)Ljava/lang/Boolean;
/*59*/   38d8-2   invoke-method: java.lang.Boolean#valueOf:(Z)Ljava/lang/Boolean;
/*59*/   38d8-3   invoke-method: java.lang.Boolean#valueOf:(Z)Ljava/lang/Boolean;
/*59*/   38d8-4   invoke-method: java.lang.Boolean#valueOf:(Z)Ljava/lang/Boolean;
/*59*/   38d8-5   invoke-method: java.lang.Boolean#valueOf:(Z)Ljava/lang/Boolean;
/*59*/   395b-3   invoke-method: kotlin.collections.CollectionsKt#listOf:([Ljava/lang/Object;)Ljava/util/List;
/*88*/   0ee8-3   invoke-method: kotlin.collections.CollectionsKt#collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
/*88*/   f0bd-3   invoke-method: java.util.ArrayList#<init>:(I)V
/*89*/   7cda-3   invoke-method: java.lang.Iterable#iterator:()Ljava/util/Iterator;
/*89*/   ad72-3   invoke-method: java.util.Iterator#hasNext:()Z
/*89*/   b105-3   invoke-method: java.util.Iterator#next:()Ljava/lang/Object;
/*90*/   cdc0-1   invoke-method: java.lang.Boolean#booleanValue:()Z
/*90*/   11a1-2   assign-variable: it
/*90*/   9fbd-1   assign-variable: $i$a$-map-MainApplication$index$1$1$1
/*60*/   9a06-1   invoke-method: java.io.PrintStream#println:(Z)V
/*61*/   d797-1   invoke-method: com.alibaba.fastjson.JSONObject#<init>:()V
/*91*/   fd39-1   invoke-method: java.util.Collection#add:(Ljava/lang/Object;)Z
/*92*/   fd39-2   invoke-method: java.util.Collection#add:(Ljava/lang/Object;)Z
/*67*/   962f-1   invoke-method: com.seewo.common.util.ResponseBuilder#<init>:()V
/*67*/   32f7-1   invoke-method: com.seewo.common.util.ResponseBuilder#ok:()Lcom/seewo/study/minder/common/util/ResponseBuilder;
/*67*/   7c58-1   invoke-method: com.seewo.common.util.ResponseBuilder#data:(Ljava/lang/Object;)Lcom/seewo/common/util/ResponseBuilder;
/*67*/   7be4-1   invoke-method: com.seewo.common.util.ResponseBuilder#build:()Lcom/alibaba/fastjson/JSONObject;
/*

@aresLD
Copy link
Contributor

aresLD commented Jul 13, 2023

已自行打包后吃到红利,过来还愿

@tanoak10
Copy link

Is there a plan to merge this feature?

@isadliliying
Copy link
Author

变更了实现方式:
#2852

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants