diff --git a/libraries-5/pom.xml b/libraries-5/pom.xml
index 74326251d089..451acbe83931 100644
--- a/libraries-5/pom.xml
+++ b/libraries-5/pom.xml
@@ -132,6 +132,26 @@
lanterna
${lanterna.version}
+
+ org.soot-oss
+ sootup.core
+ ${sootup.version}
+
+
+ org.soot-oss
+ sootup.java.core
+ ${sootup.version}
+
+
+ org.soot-oss
+ sootup.java.sourcecode
+ ${sootup.version}
+
+
+ org.soot-oss
+ sootup.java.bytecode
+ ${sootup.version}
+
org.springframework.boot
spring-boot-starter-test
@@ -149,6 +169,7 @@
1.29.2
7.28.1
0.14.1
+ 1.3.0
diff --git a/libraries-5/src/test/java/com/baeldung/sootup/AnalyzeUnitTest.java b/libraries-5/src/test/java/com/baeldung/sootup/AnalyzeUnitTest.java
new file mode 100644
index 000000000000..709269529bb3
--- /dev/null
+++ b/libraries-5/src/test/java/com/baeldung/sootup/AnalyzeUnitTest.java
@@ -0,0 +1,58 @@
+package com.baeldung.sootup;
+
+import org.junit.jupiter.api.Test;
+import sootup.core.inputlocation.AnalysisInputLocation;
+import sootup.java.bytecode.inputlocation.JavaClassPathAnalysisInputLocation;
+import sootup.java.bytecode.inputlocation.JrtFileSystemAnalysisInputLocation;
+import sootup.java.bytecode.inputlocation.OTFCompileAnalysisInputLocation;
+import sootup.java.core.views.JavaView;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class AnalyzeUnitTest {
+ @Test
+ void whenAnalyzingTheJvm_thenWeCanListClasses() {
+ AnalysisInputLocation inputLocation = new JrtFileSystemAnalysisInputLocation();
+
+ JavaView view = new JavaView(inputLocation);
+
+ assertThat(view.getClasses()).isNotEmpty();
+ }
+
+ @Test
+ void whenAnalyzingThisTestClass_thenWeCanListClasses() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/AnalyzeUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ assertEquals(1, view.getClasses().size());
+ }
+
+ @Test
+ void whenAnalyzingAString_thenWeCanListClasses() throws IOException {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/AnalyzeUnitTest.java");
+ String javaContents = Files.readString(javaFile);
+
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation("AnalyzeUnitTest.java", javaContents);
+
+ JavaView view = new JavaView(inputLocation);
+
+ assertEquals(1, view.getClasses().size());
+ }
+
+ @Test
+ void whenAnalyzingCompiledByteCode_thenWeCanListClasses() {
+ AnalysisInputLocation inputLocation = new JavaClassPathAnalysisInputLocation("target/classes");
+
+ JavaView view = new JavaView(inputLocation);
+
+ assertThat(view.getClasses()).isNotEmpty();
+ }
+}
diff --git a/libraries-5/src/test/java/com/baeldung/sootup/ClassUnitTest.java b/libraries-5/src/test/java/com/baeldung/sootup/ClassUnitTest.java
new file mode 100644
index 000000000000..ba7256df479d
--- /dev/null
+++ b/libraries-5/src/test/java/com/baeldung/sootup/ClassUnitTest.java
@@ -0,0 +1,72 @@
+package com.baeldung.sootup;
+
+import org.junit.jupiter.api.Test;
+import sootup.core.IdentifierFactory;
+import sootup.core.inputlocation.AnalysisInputLocation;
+import sootup.core.model.SootClass;
+import sootup.core.types.ClassType;
+import sootup.java.bytecode.inputlocation.OTFCompileAnalysisInputLocation;
+import sootup.java.core.JavaSootClass;
+import sootup.java.core.views.JavaView;
+
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class ClassUnitTest {
+ @Test
+ void whenAnalyzingThisTestClass_thenWeCanGetASingleClass() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/ClassUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ IdentifierFactory identifierFactory = view.getIdentifierFactory();
+ ClassType javaClass = identifierFactory.getClassType("com.baeldung.sootup.ClassUnitTest");
+
+ Optional sootClass = view.getClass(javaClass);
+ assertTrue(sootClass.isPresent());
+
+ JavaSootClass classUnitTest = sootClass.get();
+ assertTrue(classUnitTest.isPublic());
+ assertTrue(classUnitTest.isConcrete());
+ assertFalse(classUnitTest.isFinal());
+ assertFalse(classUnitTest.isEnum());
+ }
+
+ @Test
+ void whenAnalyzingThisTestClass_thenWeCanGetTheSuperclass() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/ClassUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ IdentifierFactory identifierFactory = view.getIdentifierFactory();
+ ClassType javaClass = identifierFactory.getClassType("com.baeldung.sootup.ClassUnitTest");
+
+ SootClass sootClass = view.getClassOrThrow(javaClass);
+ Optional extends ClassType> superclass = sootClass.getSuperclass();
+
+ assertTrue(superclass.isPresent());
+ assertEquals("java.lang.Object", superclass.get().getFullyQualifiedName());
+ }
+
+ @Test
+ void whenAnalyzingThisTestClass_thenWeCanGetTheInterfaces() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/ClassUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ IdentifierFactory identifierFactory = view.getIdentifierFactory();
+ ClassType javaClass = identifierFactory.getClassType("com.baeldung.sootup.ClassUnitTest");
+
+ SootClass sootClass = view.getClassOrThrow(javaClass);
+ Set extends ClassType> interfaces = sootClass.getInterfaces();
+
+ assertTrue(interfaces.isEmpty());
+ }
+
+}
diff --git a/libraries-5/src/test/java/com/baeldung/sootup/FieldUnitTest.java b/libraries-5/src/test/java/com/baeldung/sootup/FieldUnitTest.java
new file mode 100644
index 000000000000..310292b35847
--- /dev/null
+++ b/libraries-5/src/test/java/com/baeldung/sootup/FieldUnitTest.java
@@ -0,0 +1,54 @@
+package com.baeldung.sootup;
+
+import org.junit.jupiter.api.Test;
+import sootup.core.IdentifierFactory;
+import sootup.core.inputlocation.AnalysisInputLocation;
+import sootup.core.model.SootClass;
+import sootup.core.model.SootField;
+import sootup.core.types.ClassType;
+import sootup.java.bytecode.inputlocation.OTFCompileAnalysisInputLocation;
+import sootup.java.core.views.JavaView;
+
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class FieldUnitTest {
+ private String aField;
+
+ @Test
+ void whenAnalyzingThisClass_thenWeCanAccessFields() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/FieldUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ IdentifierFactory identifierFactory = view.getIdentifierFactory();
+ ClassType javaClass = identifierFactory.getClassType("com.baeldung.sootup.FieldUnitTest");
+
+ SootClass sootClass = view.getClassOrThrow(javaClass);
+ Set extends SootField> fields = sootClass.getFields();
+ assertEquals(1, fields.size());
+ }
+
+ @Test
+ void whenAnalyzingThisClass_thenWeCanAccessASingleField() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/FieldUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ IdentifierFactory identifierFactory = view.getIdentifierFactory();
+ ClassType javaClass = identifierFactory.getClassType("com.baeldung.sootup.FieldUnitTest");
+
+ SootClass sootClass = view.getClassOrThrow(javaClass);
+ Optional extends SootField> field = sootClass.getField("aField");
+ assertTrue(field.isPresent());
+
+ SootField sootField = field.get();
+ assertTrue(sootField.isPrivate());
+ assertFalse(sootField.isStatic());
+ }
+}
diff --git a/libraries-5/src/test/java/com/baeldung/sootup/MethodBodyUnitTest.java b/libraries-5/src/test/java/com/baeldung/sootup/MethodBodyUnitTest.java
new file mode 100644
index 000000000000..079523e46986
--- /dev/null
+++ b/libraries-5/src/test/java/com/baeldung/sootup/MethodBodyUnitTest.java
@@ -0,0 +1,91 @@
+package com.baeldung.sootup;
+
+import org.junit.jupiter.api.Test;
+import sootup.core.IdentifierFactory;
+import sootup.core.graph.StmtGraph;
+import sootup.core.inputlocation.AnalysisInputLocation;
+import sootup.core.jimple.common.stmt.Stmt;
+import sootup.core.model.Body;
+import sootup.core.model.SootClass;
+import sootup.core.model.SootMethod;
+import sootup.core.types.ClassType;
+import sootup.java.bytecode.inputlocation.OTFCompileAnalysisInputLocation;
+import sootup.java.core.views.JavaView;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Optional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class MethodBodyUnitTest {
+ @Test
+ void whenAnalyzingAMethod_thenWeCanAccessTheLocals() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/MethodBodyUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ IdentifierFactory identifierFactory = view.getIdentifierFactory();
+ ClassType javaClass = identifierFactory.getClassType("com.baeldung.sootup.MethodBodyUnitTest");
+
+ SootClass sootClass = view.getClassOrThrow(javaClass);
+ Optional extends SootMethod> method = sootClass.getMethod("someMethod",
+ List.of(
+ identifierFactory.getClassType("java.lang.String")
+ ));
+ assertTrue(method.isPresent());
+
+ SootMethod sootMethod = method.get();
+
+ Body methodBody = sootMethod.getBody();
+ assertThat(methodBody.getLocalCount()).isGreaterThan(0);
+ var thisLocal = methodBody.getLocals()
+ .stream()
+ .filter(local -> local.getName().equals("this"))
+ .findFirst();
+ assertTrue(thisLocal.isPresent());
+ assertEquals(javaClass, thisLocal.get().getType());
+ }
+
+ @Test
+ void whenAnalyzingAMethod_thenWeCanAccessTheCallGraph() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/MethodBodyUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ IdentifierFactory identifierFactory = view.getIdentifierFactory();
+ ClassType javaClass = identifierFactory.getClassType("com.baeldung.sootup.MethodBodyUnitTest");
+
+ SootClass sootClass = view.getClassOrThrow(javaClass);
+ Optional extends SootMethod> method = sootClass.getMethod("someMethod",
+ List.of(
+ identifierFactory.getClassType("java.lang.String")
+ ));
+ assertTrue(method.isPresent());
+
+ SootMethod sootMethod = method.get();
+
+ Body methodBody = sootMethod.getBody();
+ StmtGraph> stmtGraph = methodBody.getStmtGraph();
+ List stmts = stmtGraph.getStmts();
+
+ assertThat(stmts).hasSize(7);
+ assertThat(stmts.get(0)).asString().isEqualTo("this := @this: com.baeldung.sootup.MethodBodyUnitTest");
+ assertThat(stmts.get(1)).asString().isEqualTo("l1 := @parameter0: java.lang.String");
+ assertThat(stmts.get(2)).asString().isEqualTo("l2 = virtualinvoke l1.()");
+ assertThat(stmts.get(3)).asString().isEqualTo("$stack3 = ");
+ assertThat(stmts.get(4)).asString().isEqualTo("$stack4 = dynamicinvoke \"makeConcatWithConstants\" (l2) (\"Hello, \\u0001\")");
+ assertThat(stmts.get(5)).asString().isEqualTo("virtualinvoke $stack3.($stack4)");
+ assertThat(stmts.get(6)).asString().isEqualTo("return");
+ }
+
+
+ private void someMethod(String name) {
+ var capitals = name.toUpperCase();
+ System.out.println("Hello, " + capitals);
+ }
+}
diff --git a/libraries-5/src/test/java/com/baeldung/sootup/MethodUnitTest.java b/libraries-5/src/test/java/com/baeldung/sootup/MethodUnitTest.java
new file mode 100644
index 000000000000..c04f635854db
--- /dev/null
+++ b/libraries-5/src/test/java/com/baeldung/sootup/MethodUnitTest.java
@@ -0,0 +1,77 @@
+package com.baeldung.sootup;
+
+import org.junit.jupiter.api.Test;
+import sootup.core.IdentifierFactory;
+import sootup.core.inputlocation.AnalysisInputLocation;
+import sootup.core.model.SootClass;
+import sootup.core.model.SootMethod;
+import sootup.core.types.ClassType;
+import sootup.java.bytecode.inputlocation.OTFCompileAnalysisInputLocation;
+import sootup.java.core.views.JavaView;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class MethodUnitTest {
+
+ @Test
+ void whenAnalyzingThisClass_thenWeCanAccessMethods() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/MethodUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ IdentifierFactory identifierFactory = view.getIdentifierFactory();
+ ClassType javaClass = identifierFactory.getClassType("com.baeldung.sootup.MethodUnitTest");
+
+ SootClass sootClass = view.getClassOrThrow(javaClass);
+ Set extends SootMethod> methods = sootClass.getMethods();
+ assertThat(methods).isNotEmpty();
+ }
+
+ @Test
+ void whenAnalyzingThisClass_thenWeCanAccessASingleMethod() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/MethodUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ IdentifierFactory identifierFactory = view.getIdentifierFactory();
+ ClassType javaClass = identifierFactory.getClassType("com.baeldung.sootup.MethodUnitTest");
+
+ SootClass sootClass = view.getClassOrThrow(javaClass);
+ Optional extends SootMethod> method = sootClass.getMethod("someMethod",
+ List.of(
+ identifierFactory.getClassType("java.lang.String")
+ ));
+ assertTrue(method.isPresent());
+
+ SootMethod sootMethod = method.get();
+ assertTrue(sootMethod.isPrivate());
+ assertTrue(sootMethod.isConcrete());
+ }
+
+ @Test
+ void whenAnalyzingThisClass_thenWeCanListMethodsByName() {
+ Path javaFile = Path.of("src/test/java/com/baeldung/sootup/MethodUnitTest.java");
+ AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(javaFile);
+
+ JavaView view = new JavaView(inputLocation);
+
+ IdentifierFactory identifierFactory = view.getIdentifierFactory();
+ ClassType javaClass = identifierFactory.getClassType("com.baeldung.sootup.MethodUnitTest");
+
+ SootClass sootClass = view.getClassOrThrow(javaClass);
+ Set extends SootMethod> method = sootClass.getMethodsByName("someMethod");
+ assertEquals(2, method.size());
+ }
+
+ private void someMethod(String name) {}
+ private void someMethod(int value) {}
+}