提问人:Mark Renouf 提问时间:2/10/2011 最后编辑:Christophe RoussyMark Renouf 更新时间:9/26/2022 访问量:29136
Java 调用图的静态分析
Static analysis of Java call graph
问:
我想做的是扫描一组 Java 类,并跟踪来自抽象类的特定方法的所有方法调用,并在该上下文中构建执行某些操作的所有代码的列表(在本例中,实例化某个类的实例)。我想知道,行号和提供的参数。
我已经开始研究 BCEL,但它似乎没有内置调用图跟踪?我犹豫要不要自己写,因为获得重载、类型签名和多态调度可能很棘手。
我半信半疑地期望存在一个工具或示例代码,但我还没有找到任何东西。真的感觉我即将重新发明一个轮子。但如果我这样做,它将是一个开源轮子,可在 GitHub 上获得 ;-)
PS:你会发现现有的问题“如何生成一个Java调用图”,因为它听起来是一样的,但它根本不是我需要的。
答:
听起来你想要一些提供对抽象语法和完整符号表的访问的东西。然后,对根植于抽象方法的每个实现方法(如符号表所示)的调用图中函数的 AST 进行自定义扫描,使您有机会找到其类型为特定感兴趣类的新操作。
DMS软件再造工具包是一种通用编译器技术,提供解析、AST构建/导航、符号表构建/导航、控制流、数据流和调用图构建等基本服务。DMS 有一个可选的 Java 前端,它提供了一个完整的 Java 解析器,构建了 Java AST 和符号表,并且可以构造调用图。Java 前端还可以读取 .class 文件;你不清楚你是否也想爬进班级文件,寻找信息。
你想要的答案不是现成的。您需要构建一些自定义代码来实现第一段中的想法,但 DMS 可以提供大部分原材料。它没有提供 .class 文件中的太多细节(这些文件主要用于解析源代码中的类型)。
烟灰应该可以让你轻松实现你想要的东西:http://www.sable.mcgill.ca/soot/
它可以全自动构建精确的呼叫图。
您可以在此处找到所有必要的文档:http://www.sable.mcgill.ca/soot/tutorial/index.html
此外,还有一个活跃的 Soot 邮件列表。
评论
你可以试试 JavaDepend ,它提供了依赖项和指标所需的许多功能,它还提供了一个像 SQL 这样的 CQL 来请求您的代码库。
披露:这是一个商业软件。
您可以将 Doxygen 与 Graphviz 一起使用。它易于安装和使用。
您可以使用 java-callgraph 工具套件为 Java 创建足够准确的静态和动态调用图。
对于“最近的”Eclipse 安装(相对于问题),请参阅 Certiv CallGraph。
CallGraph 支持对程序调用关系和流排序进行图形分析。还支持探索扩展的类继承层次结构。
调用路径分析和类层次结构解析是使用 JDT 平台搜索和调用层次结构机制执行的。
序列图是通过对任何选定类或方法的 JDT 平台 AST 的静态分析生成的。
使用 Zest 作为图形可视化引擎。
您可以通过 Eclipse 市场安装它。我没有参与制作这个。 您不能缩小,这不是很实用,但支持序列图,这很好,允许根据需要打开/关闭节点以进一步挖掘。
要求:
Eclipse 4.6 (Neon) on Java 8 VM
Eclipse Zest Visualization Toolkit 1.7
Eclipse 公共许可证 v1.0
您可以看到:https://github.com/Adrninistrator/java-all-call-graph/blob/main/README-en.md
输出示例:
- 向上
org.mybatis.spring.SqlSessionUtils:lambda$closeSqlSession$6(org.apache.ibatis.session.SqlSession)
[0]#org.mybatis.spring.SqlSessionUtils:lambda$closeSqlSession$6(org.apache.ibatis.session.SqlSession)
[1]# org.mybatis.spring.SqlSessionUtils:closeSqlSession(org.apache.ibatis.session.SqlSession,org.apache.ibatis.session.SqlSessionFactory)
[2]# org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor:invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[]) !entry!
org.mybatis.spring.SqlSessionUtils:lambda$getSqlSession$0()
[0]#org.mybatis.spring.SqlSessionUtils:lambda$getSqlSession$0()
[1]# org.mybatis.spring.SqlSessionUtils:getSqlSession(org.apache.ibatis.session.SqlSessionFactory) !entry!
[1]# org.mybatis.spring.SqlSessionUtils:getSqlSession(org.apache.ibatis.session.SqlSessionFactory,org.apache.ibatis.session.ExecutorType,org.springframework.dao.support.PersistenceExceptionTranslator)
[2]# org.mybatis.spring.SqlSessionUtils:getSqlSession(org.apache.ibatis.session.SqlSessionFactory) !entry!
[2]# org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor:invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[]) !entry!
- 向下
org.mybatis.spring.SqlSessionFactoryBean:scanClasses(java.lang.String,java.lang.Class)
[0]#org.mybatis.spring.SqlSessionFactoryBean:scanClasses(java.lang.String,java.lang.Class)
[1]# org.springframework.util.StringUtils:tokenizeToStringArray(java.lang.String,java.lang.String)
[1]# org.springframework.util.ClassUtils:convertClassNameToResourcePath(java.lang.String)
[1]# org.springframework.core.io.support.ResourcePatternResolver:getResources(java.lang.String)
[1]# org.springframework.core.type.classreading.MetadataReaderFactory:getMetadataReader(org.springframework.core.io.Resource)
[1]# org.springframework.core.type.classreading.MetadataReader:getClassMetadata()
[1]# org.springframework.core.type.ClassMetadata:getClassName()
[1]# org.apache.ibatis.io.Resources:classForName(java.lang.String)
[2]# org.apache.ibatis.io.ClassLoaderWrapper:classForName(java.lang.String)
[3]# org.apache.ibatis.io.ClassLoaderWrapper:getClassLoaders(java.lang.ClassLoader)
[3]# org.apache.ibatis.io.ClassLoaderWrapper:classForName(java.lang.String,java.lang.ClassLoader[])
[1]# org.mybatis.spring.SqlSessionFactoryBean:lambda$scanClasses$19(org.springframework.core.io.Resource,java.lang.Throwable)
一个很棒的 git 存储库就在这里:
https://github.com/gajanandjha/Java-Call-Tree-Generator
它生成 Java 进程中所有线程的调用树,然后 repo README 注释为我们提供了一些 Unix 魔术命令来获取我们需要的线程跟踪,并生成一个简单的网页,其中包含线程在流中访问过的所有方法的树视图。
评论