【问题标题】:JAVA - how to print trace of methods/objects used from an external jarJAVA - 如何打印从外部 jar 使用的方法/对象的跟踪
【发布时间】:2012-08-31 23:13:05
【问题描述】:

我目前正在测试在罐子中提供给我们的 api。 我正在尝试获取我们已触及或至少我们的源代码引用的 jar 方法和对象的“覆盖范围”或列表。

我们拥有或将拥有的是“这里是 API 列表”的文本格式

我们需要交叉引用我们自己的应用程序,以确保我们涵盖了列出的 API。

...

这是一个简化的示例... 下面我列出了一个可从 jar 获取的外部代码的示例,以及我们使用这些 API 的代码。

-- EXTERNAL_USE_CLASS -- 使用我们需要覆盖的公共 API 模拟外部 JAR

package external_api;

public class EXTERNAL_USE_CLASS {
    String myString;
    Integer myInteger;
    Boolean has_ran;
    public EXTERNAL_USE_CLASS() {
        myString = "initial_string";
        myInteger = 4;
        has_ran = false;
    }
    public String getMyString() {
        return myString;
    }
    public void setMyString(String myString) {
        this.myString = myString;
    }
    public Integer getMyInteger() {
        return myInteger;
    }
    public void setMyInteger(Integer myInteger) {
        this.myInteger = myInteger;
    }
    public Boolean getHas_ran() {
        return has_ran;
    }
    public void setHas_ran(Boolean has_ran) {
        this.has_ran = has_ran;
    }
}

我的项目会将上述内容作为 jar 导入并将其添加到构建路径中。 我的代码将执行的操作是这样的:

UseExtJar -- 使用外部 jars 对象/方法模拟我们的测试应用程序

import external_api.EXTERNAL_USE_CLASS;

public class UseExtJar {
    static EXTERNAL_USE_CLASS u = new EXTERNAL_USE_CLASS();

    //below is callable via a CLI interface test APP.
    public static void test_basics() {
        Boolean hasRan = u.getHas_ran();
        Integer getInt = u.getMyInteger();
        String getString = u.getMyString();
        System.out.println("u.getHas_ran()"+hasRan);
        System.out.println("u.getMyInteger()"+getInt);
        System.out.println("u.getMyString()"+getString);
    }
}

而我有兴趣公开的是从外部 Jar 中接触到的所有 API。

(即这些行)

    Boolean hasRan = u.getHas_ran();
    Integer getInt = u.getMyInteger();
    String getString = u.getMyString();

如果可能的话......我希望能够打印出一些报告,大意是说

您的对象方法“test_basics”使用了以下 api:
--external_api.EXTERNAL_USE_CLASS.getHas_ran()
--external_api.EXTERNAL_USE_CLASS.getMyInteger() --external_api.EXTERNAL_USE_CLASS.getMyString()

我必须通过进入我的测试类并在 eclipse 中右键单击并说“复制限定名称”来获得上述名称。

如果我们必须为 1,000 个 API 执行此操作,这会有点痛苦……我只是想出了一些方法可以在逻辑上打印出跟踪。

可能我只是不知道正确的谷歌搜索词,这是一个常见的简单任务。

非常感谢任何帮助/指针。

【问题讨论】:

    标签: java jar trace


    【解决方案1】:

    如果您知道类的名称以获取有关它的信息,则可以使用反射解决部分问题。你可以打印甚至练习类中的方法

    import java.lang.reflect.*;
    
    public class DumpMethods { 
    
      public static void main(String args[])
      {
         try {
            Class c = Class.forName("MyClassName");
            Method m[] = c.getDeclaredMethods();
            for (int i = 0; i < m.length; i++)
            System.out.println(m[i].toString());
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
    }
    

    这里是初学者的tutorial

    对你来说,影响一些库代码来减轻你的一些负担并不是一件可怕的事情。

    不幸的是,分析一个 jar 的内容并不是那么简单。一旦 jar 的类被加载到 jar 类的概念中就消失了。默认的类加载器只使用包名作为标识唯一类并决定它是否存在于类加载器中的键。因此,您甚至无法真正遍历包中的类,更不用说 jar 的内容了。

    为此,您可以创建一个自定义类加载器,用于分析 jar 并记录从类路径中获取的信息。

    【讨论】:

      【解决方案2】:

      当你必须为每个使用的 API 类编写一个模拟类时

      System.out.println(MyMockedClass.class.getCanonicalName());
      

      获取您正在模拟的类的限定名称。

      像这样的

      Object doMethod(String name){
          try {
              Method method = u.getClass().getDeclaredMethod(name);
              System.out.println("called: " + name);
              try {
                  return (String)method.invoke(this);
              } catch (IllegalArgumentException e) {
                  return false;
              } catch (IllegalAccessException e) {
                  return false;
              } catch (InvocationTargetException e) {
                  return false;
              }
          } catch (NoSuchMethodException e) {
              return false;
          }
      }
      

      可以为您提供一种调用和打印您调用的每个方法的方法。

      对于使用参数调用的方法会变得更加困难。

      【讨论】:

        【解决方案3】:

        谢谢。

        我按照您的建议从反射开始,然后转向 ASM,因为我正在使用字节码。


        我从引用 ASM 和反射的 2 个链接中提取了我的参考

        Java: Easy way to get method stub out of class files within a JAR file? Reflection?

        How can I find all the methods that call a given method in Java?


        我的解决方案基本上分两步解决问题

        1。从外部 jar 中读取所有目标方法

        通过 ASM,读入所有满足类路径 (com.my.class.object.*) 和一些 opt-code 过滤器(非私有、非抽象等)的公共类/方法对象并附加所有满足对存储类/方法的对象列表的过滤。

        2。 foreach 目标方法,检查它是否存在于我们的源代码中。

        对于找到的每个目标类/方法,就像上面提供的链接一样,我可以检查位置,并使用行/文件名等打印所有出现。

        【讨论】:

          猜你喜欢
          • 2016-11-17
          • 2011-11-06
          • 2019-09-13
          • 1970-01-01
          • 2011-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多