拓展阅读
开源 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息)
开源 Junit performance rely on junit5 and jdk8+.(java 性能测试框架。性能测试。压测。测试报告生成。)
test fuzz-01-模糊测试(Fuzz Testing)
Soot
重要提示:Soot现已由SootUp接替!
在2022年12月,我们正式发布了SootUp,这是Soot的一个版本,具有完全经过重新设计的、更模块化、可测试、可维护和可用的架构。如果您想要开始一个新的程序分析项目,请查看一下。
Soot现已支持Java 9模块! 尝试并参与Soot的Java 9最新开发。
已经测试并且可用的有:
- 自动模块(从模块路径中的jar自动创建的模块)
- 命名模块
- 爆炸式模块
- 模块化的jar文件
- 在Soot的ModuleScene中解析模块
- Spark
目前尚未实现的有:
- 匿名模块(混合模块路径和类路径)
- 多模块的jar文件
什么是Soot?
Soot是一个Java优化框架。
它提供了四种用于分析和转换Java字节码的中间表示:
- Baf:一个简化的字节码表示,易于操作。
- Jimple:一个适用于优化的带类型的3地址中间表示。
- Shimple:Jimple的SSA变体。
- Grimp:适用于反编译和代码检查的Jimple的聚合版本。
详细信息请参阅 https://soot-oss.github.io/soot。
如何开始使用Soot?
我们在wiki上提供了一些关于Soot的文档,还有许多关于Soot的教程。
有关详细信息,请考虑查阅Soot的JavaDoc和选项文档。
将Soot包含到您的项目中
每次提交到主分支(master)时,都会构建一个Soot发布版本。
您可以通过Maven、Gradle、SBT等工具使用以下坐标将Soot作为依赖项引入项目:
<dependencies>
<dependency>
<groupId>org.soot-oss</groupId>
<artifactId>soot</artifactId>
<version>4.3.0</version>
</dependency>
</dependencies>
您还可以获取主分支的旧版本构建。
可以在Maven Central上找到所有版本的构建列表。
每次提交到开发分支(develop)时,都会构建一个Soot SNAPSHOT版本。
您可以通过Maven、Gradle、SBT等工具使用以下坐标将Soot作为依赖项引入项目:
<dependencies>
<dependency>
<groupId>org.soot-oss</groupId>
<artifactId>soot</artifactId>
<version>4.4.0-SNAPSHOT</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
您还可以获取开发分支的旧版本构建。
可以在Maven Central上找到所有版本的构建列表。
如何获取没有Maven的Soot? 我们推荐使用Maven来使用Soot,您可以直接获取Soot的最新发行构建。您也可以直接获取Soot的最新SNAPSHOT构建。
soot-<RELEASE>-jar-with-dependencies.jar
文件是一个包含所有必需库的全功能文件。
soot-<RELEASE>.jar
文件仅包含Soot,允许您手动选择依赖项,按需加载。如果您不想处理依赖关系,我们建议使用前者。
自行构建Soot
如果您无法使用预构建版本并需要自行构建Soot,请考虑查阅wiki以获取更多详细步骤。
关于Soot源代码
Soot遵循git-flow约定。发布和热修复版本都在主分支(master)中维护。
开发发生在开发分支(develop)中。要获取Soot的最新版本,请查看后者。
如有任何问题,请咨询Soot邮件列表:http://www.sable.mcgill.ca/mailman/listinfo/soot-list/
如何贡献给Soot?
我们欢迎以GitHub拉取请求的形式提交对Soot的任意改进。在设置拉取请求之前,请阅读我们的贡献指南。
请帮助我们改进Soot!
您正在使用Soot并希望在未来帮助我们支持它吗?那么,请通过填写这个小型网络表单来支持我们。
这样,您可以通过两种方式帮助我们:
-
通过告诉我们如何改进Soot,您可以直接帮助我们确定新计划功能的优先级。
-
通过提供您的姓名和机构,您可以帮助我们展示Soot庞大的用户群体。谢谢!
如何使用Soot的Java 9功能?
如果要在Java 8之后的版本中运行Soot,只需像往常一样运行即可。
如果要使用Java 8执行Soot但分析Java 8之后的项目,或反之,可参考下文。
从源代码使用
要从Java中加载Soot的ModuleScene中的模块:
// 配置Soot的选项,请参考下面的示例配置
Options.v().set_soot_modulepath(modulePath);
// 将模块中的类加载到Soot中
// 这里,getClassUnderModulePath() 期望使用上面所示的Options类设置模块路径
Map<String, List<String>> map = ModulePathSourceLocator.v().getClassUnderModulePath(modulePath);
for (String module : map.keySet()) {
for (String klass : map.get(module)) {
logger.info("Loaded Class: " + klass + "\n");
loadClass(klass, false, module);
// loadClass() 方法在下面定义
}
}
// 所有类加载完成后必须调用此方法
Scene.v().loadNecessaryClasses();
public static SootClass loadClass(String name, boolean main, String module) {
SootClass c = ModuleScene.v().loadClassAndSupport(name, Optional.of(module));
c.setApplicationClass();
if (main)
Scene.v().setMainClass(c);
return c;
}
ModuleUtil.module_mode()
可以帮助您检查在Soot中是否启用了模块。这是根据是否使用Options类设置了模块路径来完成的。
示例配置:Java 8,Java >= 9 类路径,Java >= 9 模块路径
if (java < 9) { // 当目标基准测试使用Java < 9且因此没有模块时
Options.v().set_prepend_classpath(true);
Options.v().set_process_dir(Arrays.asList(applicationClassPath().split(File.pathSeparator)));
Options.v().set_soot_classpath(sootClassPath());
}
if (java >= 9 && USE_CLASSPATH) { // 当目标基准测试使用Java >= 9且不需要模块支持时
Options.v().set_soot_classpath("VIRTUAL_FS_FOR_JDK" + File.pathSeparator + sootClassPath());
Options.v().set_process_dir(Arrays.asList(applicationClassPath().split(File.pathSeparator)));
}
if (java >= 9 && USE_MODULEPATH) { // 当目标基准测试使用Java >= 9且需要模块支持时
Options.v().set_prepend_classpath(true);
Options.v().set_soot_modulepath(sootClassPath());
Options.v().set_process_dir(Arrays.asList(applicationClassPath().split(File.pathSeparator)));
}
在上述示例中,applicationClassPath()
应替换为Soot分析的应用程序类的路径,sootClassPath()
应替换为Soot类路径。
从命令行使用
要使用Java 1.9执行Soot,但分析类路径运行,与以前一样运行:
java -cp soot-trunk.jar soot.Main --process-dir directoryToAnalyse
如果要明确指定类路径,请运行:
java -cp soot-trunk.jar soot.Main -cp VIRTUAL_FS_FOR_JDK --process-dir directoryToAnalyse
值VIRTUAL_FS_FOR_JDK
表示Soot应该搜索Java(>9)的虚拟文件系统jrt:/
中的类,即使Soot没有在模块模式下执行。
要在Java 1.8中运行Soot并加载模块和类,请运行:
java -cp PATH_TO_JAVA9/jrt-fs.jar:soot-trunk.jar soot.Main -pp -soot-modulepath modules/
请将 PATH_TO_JAVA9
替换为Java 9的本地安装路径。
jrt-fs.jar
是Java 9使用的jrt://文件系统的内置NIO文件系统提供程序,用于替换rt.jar
。
chat
详细介绍一下 soot
Soot是一个用于分析和转换Java字节码的开源框架。它为静态分析、优化和深入理解Java程序提供了强大的工具。以下是关于Soot的详细介绍:
1. 目标和用途:
- 静态分析: Soot主要用于进行静态分析,即在程序运行之前分析程序的结构和性质。
- 优化: Soot可以应用多种优化技术,改善程序的性能和资源利用率。
- 转换: Soot允许用户对Java字节码进行各种转换,包括插桩(instrumentation)、重构(refactoring)等。
2. 主要特性:
- 模块化设计: Soot采用模块化的设计,允许用户选择性地使用其功能。这使得它可以灵活地嵌入到各种项目中。
- 可扩展性: Soot提供了丰富的API,使得开发人员可以轻松地扩展和自定义分析和转换。
- 支持多种分析和优化: Soot支持诸如活跃变量分析、数据流分析、切片分析等多种分析技术,同时也支持诸如内联、常量折叠等多种优化技术。
3. 主要组件:
- Front-end(前端): 负责将Java源代码或字节码转换为内部表示形式。
- Intermediate Representation(中间表示): Soot使用Shimple作为其内部表示,一种高级的SSA(Static Single Assignment)形式。
- Analysis Packs: 包含各种分析和优化的集合,用户可以选择性地启用这些分析和优化。
4. 使用场景:
- 研究: 由于其灵活性和可扩展性,Soot在研究领域中经常被用于开发新的静态分析技术和优化算法。
- 工具开发: Soot被广泛应用于开发与Java字节码相关的工具,如代码检查工具、测试工具等。
5. 工作流程:
- 加载字节码: Soot首先加载Java字节码,可以是从Java源代码编译而来,也可以是从已有的.class文件中提取。
- 分析: Soot执行各种分析,例如数据流分析、活跃变量分析等,以理解程序的结构和行为。
- 优化: 基于分析结果,Soot可以应用各种优化,改进程序的性能。
- 输出: Soot可以将分析或转换后的结果输出为新的字节码文件或其他形式。
6. 社区和支持:
- Soot是一个活跃的开源项目,拥有一个积极的社区。用户可以在论坛、邮件列表等地方获取支持和交流经验。
总体而言,Soot是一个功能强大的工具,适用于对Java程序进行深入分析和优化的场景。由于其模块化和可扩展的设计,它在研究和工业界都得到了广泛的应用。
给一个 soot 具体的 java 入门例子
以下是一个简单的使用 Soot 进行静态分析的 Java 入门示例。这个示例使用 Soot 分析一个简单的 Java 类,获取该类的方法和字段信息。
首先,确保你已经下载并设置好 Soot。你可以在 Soot 官方网站 上获取最新版本的 Soot。
然后,创建一个 Java 类(例如 SampleClass.java
):
public class SampleClass {
private int sampleField;
public SampleClass() {
sampleField = 42;
}
public void sampleMethod(int parameter) {
System.out.println("Sample Method: " + parameter);
}
public static void main(String[] args) {
SampleClass sampleObj = new SampleClass();
sampleObj.sampleMethod(10);
}
}
接下来,创建一个 Java 类(例如 AnalysisExample.java
)来使用 Soot 分析 SampleClass
:
import soot.*;
public class AnalysisExample {
public static void main(String[] args) {
String classPath = "path/to/SampleClass.class"; // 替换为 SampleClass.class 的路径
// 设置 Soot
Options.v().set_verbose(true);
Options.v().set_output_format(Options.output_format_jimple);
Scene.v().setSootClassPath(classPath);
// 加载类
SootClass sootClass = Scene.v().forceResolve("SampleClass", SootClass.BODIES);
sootClass.setApplicationClass();
// 遍历类的方法
for (SootMethod method : sootClass.getMethods()) {
System.out.println("Method: " + method.getName());
}
// 遍历类的字段
for (SootField field : sootClass.getFields()) {
System.out.println("Field: " + field.getName());
}
}
}
确保替换 path/to/SampleClass.class
为 SampleClass.class
的实际路径。
在这个例子中,我们使用 Soot 分析了 SampleClass
中的方法和字段信息,并打印了它们的名称。
运行 AnalysisExample.java
,你应该能够看到输出包含了 SampleClass
中的方法和字段信息。
请注意,这只是 Soot 的一个简单用法示例。在实际的静态分析工作中,你可能需要更详细的分析和优化,具体取决于你的需求。
你可以查阅 Soot 的官方文档以获取更多详细信息和功能。
让你深入学习 soot,你会问哪10个问题?为什么?
深入学习 Soot时,你可能会问以下10个问题,这些问题可以帮助你更全面地理解 Soot 的内部机制和功能:
- Soot的主要设计目标是什么?
- 理解 Soot 的设计目标有助于确定其适用的使用场景和优势。
- Soot如何处理Java字节码?
- 了解 Soot 是如何加载、解析和分析 Java 字节码的,以及它采用的中间表示形式。
- Soot如何实现静态分析?
- 深入了解 Soot 的静态分析能力,包括数据流分析、活跃变量分析等。
- Soot中的Shimple是什么,为什么使用它?
- 了解 Shimple 是 Soot 中的一种中间表示形式,以及它相对于其他表示形式的优势。
- Soot的优化能力有哪些,如何使用?
- 掌握 Soot 提供的优化技术,包括内联、常量折叠等,以及如何在分析中应用这些优化。
- Soot如何处理Java程序中的异常?
- 了解 Soot 如何处理异常信息,包括异常的传播和处理路径。
- Soot如何与外部工具集成?
- 了解 Soot 如何与其他工具和框架集成,例如与JUnit结合进行测试生成,以及如何在实际项目中使用 Soot。
- Soot的社区活跃度如何?
- 了解 Soot 的社区活跃程度,包括问题和解决方案的讨论,以及是否有最新的版本发布。
- Soot的性能特性是什么?
- 了解 Soot 的性能,包括分析大型代码库时的效率和资源消耗。
- Soot适用于哪些应用场景?
- 了解 Soot 在哪些领域和场景中表现出色,以及它在静态分析、代码优化等方面的主要应用。
这些问题涵盖了 Soot 的核心原理、设计决策和实际应用,有助于你深入学习和有效使用 Soot 进行静态分析和代码转换。
给出一个 soot 在 静态分析 具体的例子?
静态分析是Soot强大功能之一,它允许您在不实际运行程序的情况下检查和理解代码。
以下是一个简单的Soot静态分析的例子,该例子演示如何使用Soot获取Java代码中方法的签名信息:
import soot.*;
import soot.jimple.*;
import soot.options.Options;
import java.util.Iterator;
public class SootStaticAnalysisExample {
public static void main(String[] args) {
// 设置Soot的选项
String classPath = "path/to/your/classes"; // 替换为实际的类路径
Options.v().set_soot_classpath(classPath);
Options.v().set_whole_program(true);
Options.v().setPhaseOption("jb", "use-original-names:true");
// 加载类并分析
String className = "your.package.YourClass"; // 替换为要分析的类的名称
SootClass sootClass = Scene.v().forceResolve(className, SootClass.SIGNATURES);
sootClass.setApplicationClass();
Scene.v().loadNecessaryClasses();
// 打印方法签名信息
Iterator<SootMethod> methodIterator = sootClass.getMethods().iterator();
while (methodIterator.hasNext()) {
SootMethod method = methodIterator.next();
System.out.println("Method Signature: " + method.getSignature());
}
}
}
请确保替换path/to/your/classes
和your.package.YourClass
为实际的类路径和类名。
这个简单的例子加载了指定的Java类并打印了该类中每个方法的签名信息。
在实际的静态分析中,您可能会执行更复杂的分析,如数据流分析、控制流分析等,以深入理解程序的结构和行为。
Soot提供了强大的框架,使得进行这些更深入的分析变得可能。
给出一个 soot 在 代码优化 具体的例子?
Soot在代码优化方面的应用非常广泛,它可以进行多种类型的优化,包括常见的控制流优化、数据流优化等。
以下是一个简单的Soot代码优化的例子,展示如何使用Soot进行常量传播:
import soot.*;
import soot.jimple.*;
import soot.options.Options;
public class SootConstantPropagationExample {
public static void main(String[] args) {
// 设置Soot的选项
String classPath = "path/to/your/classes"; // 替换为实际的类路径
Options.v().set_soot_classpath(classPath);
Options.v().set_whole_program(true);
Options.v().setPhaseOption("jb", "use-original-names:true");
// 加载类并进行常量传播优化
String className = "your.package.YourClass"; // 替换为要优化的类的名称
SootClass sootClass = Scene.v().forceResolve(className, SootClass.SIGNATURES);
sootClass.setApplicationClass();
Scene.v().loadNecessaryClasses();
// 进行常量传播优化
PackManager.v().getPack("jtp").add(new Transform("jtp.myTransform", new BodyTransformer() {
protected void internalTransform(Body body, String phaseName, Map<String, String> options) {
for (Unit unit : body.getUnits()) {
if (unit instanceof Stmt) {
Stmt stmt = (Stmt) unit;
if (stmt.containsInvokeExpr()) {
InvokeExpr invokeExpr = stmt.getInvokeExpr();
if (invokeExpr.getMethod().getName().equals("println")) {
// 如果调用的是System.out.println(),将其替换为常量
IntConstant constant = IntConstant.v(42); // 替换为您想要的常量值
AssignStmt assignStmt = Jimple.v().newAssignStmt(invokeExpr, constant);
body.getUnits().insertAfter(assignStmt, stmt);
body.getUnits().remove(stmt);
}
}
}
}
}
}));
// 输出优化后的方法
for (SootMethod method : sootClass.getMethods()) {
System.out.println("Optimized Method: " + method.getName());
System.out.println(method.retrieveActiveBody());
}
}
}
请确保替换path/to/your/classes
和your.package.YourClass
为实际的类路径和类名。
这个例子中,我们将System.out.println()调用替换为一个常量值,实现了简单的常量传播优化。
在实际的代码优化中,您可能会执行更复杂的优化,如内联、循环展开等,以提高程序的性能和效率。Soot为这些优化提供了强大的框架和工具。