Skip to content

Commit

Permalink
Update Gradle and add Spotless / GJF (#20)
Browse files Browse the repository at this point in the history
* Add Spotless / GJF

* Update Gradle
  • Loading branch information
msridhar authored Nov 30, 2024
1 parent 8468a38 commit fd1dbc4
Show file tree
Hide file tree
Showing 17 changed files with 442 additions and 420 deletions.
23 changes: 19 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
apply plugin: 'java-library'
apply plugin: 'application'
apply plugin: 'eclipse'
plugins {
id 'java-library'
id 'application'
id 'eclipse'
id("com.diffplug.spotless") version "6.25.0"
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}

sourceCompatibility = 11
version = '0.1'
jar {
manifest {
Expand Down Expand Up @@ -40,3 +48,10 @@ if (project.hasProperty('mainClass')) {
// use a default
mainClassName = "com.ibm.wala.examples.drivers.PDFTypeHierarchy"
}

spotless {
java {
// apply a specific flavor of google-java-format
googleJavaFormat()
}
}
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,6 @@
*******************************************************************************/
package com.ibm.wala.examples.analysis;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarFile;

import com.ibm.wala.classLoader.ArrayClass;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IField;
Expand Down Expand Up @@ -46,36 +38,39 @@
import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.intset.OrdinalSet;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarFile;

/**
* <P>
* A simple thread-level escape analysis: this code computes the set of classes of which some instance may be accessed
* by some thread other than the one that created it.
* </P>
*
* <P>
* The algorithm is not very bright; it is based on the observation that there are only three ways for an object to pass
* from one thread to another.
* A simple thread-level escape analysis: this code computes the set of classes of which some
* instance may be accessed by some thread other than the one that created it.
*
* <p>The algorithm is not very bright; it is based on the observation that there are only three
* ways for an object to pass from one thread to another.
*
* <UL>
* <LI> The object is stored into a static variable.
* <LI> The object is stored into an instance field of a Thread
* <LI> The object is reachable from a field of another escaping object.
* <LI>The object is stored into a static variable.
* <LI>The object is stored into an instance field of a Thread
* <LI>The object is reachable from a field of another escaping object.
* </UL>
* </P>
*
* <P>
* This observation is implemented in the obvious way:
*
* <p>This observation is implemented in the obvious way:
*
* <OL>
* <LI> All static fields are collected
* <LI> All Thread constructor parameters are collected
* <LI> The points-to sets of these values represent the base set of escapees.
* <LI> All object reachable from fields of these objects are added
* <LI> This process continues until a fixpoint is reached
* <LI> The abstract objects in the points-to sets are converted to types
* <LI> This set of types is returned
* <LI>All static fields are collected
* <LI>All Thread constructor parameters are collected
* <LI>The points-to sets of these values represent the base set of escapees.
* <LI>All object reachable from fields of these objects are added
* <LI>This process continues until a fixpoint is reached
* <LI>The abstract objects in the points-to sets are converted to types
* <LI>This set of types is returned
* </OL>
* </P>
*
*
* @author Julian Dolby
*/
public class SimpleThreadEscapeAnalysis extends AbstractAnalysisEngine {
Expand All @@ -85,7 +80,8 @@ public class SimpleThreadEscapeAnalysis extends AbstractAnalysisEngine {
private final String applicationMainClass;

/**
* The two input parameters define the program to analyze: the jars of .class files and the main class to start from.
* The two input parameters define the program to analyze: the jars of .class files and the main
* class to start from.
*/
public SimpleThreadEscapeAnalysis(Set<JarFile> applicationJarFiles, String applicationMainClass) {
this.applicationJarFiles = applicationJarFiles;
Expand All @@ -94,12 +90,13 @@ public SimpleThreadEscapeAnalysis(Set<JarFile> applicationJarFiles, String appli

@Override
protected CallGraphBuilder getCallGraphBuilder(
IClassHierarchy cha, AnalysisOptions options, IAnalysisCacheView cache) {
IClassHierarchy cha, AnalysisOptions options, IAnalysisCacheView cache) {
return Util.makeZeroCFABuilder(Language.JAVA, options, cache, cha, scope);
}

/**
* Given a root path, add it to the set if it is a jar, or traverse it recursively if it is a directory.
* Given a root path, add it to the set if it is a jar, or traverse it recursively if it is a
* directory.
*/
private void collectJars(File f, Set<JarFile> result) throws IOException {
if (f.isDirectory()) {
Expand All @@ -114,9 +111,7 @@ private void collectJars(File f, Set<JarFile> result) throws IOException {
}
}

/**
* Collect the set of JarFiles that constitute the system libraries of the running JRE.
*/
/** Collect the set of JarFiles that constitute the system libraries of the running JRE. */
private JarFile[] getSystemJars() throws IOException {
String javaHomePath = "garbage";
Set<JarFile> jarFiles = HashSetFactory.make();
Expand Down Expand Up @@ -148,12 +143,12 @@ private JarFile[] getSystemJars() throws IOException {
}

/**
* Take the given set of JarFiles that constitute the program, and return a set of Module files as expected by the
* WALA machinery.
* Take the given set of JarFiles that constitute the program, and return a set of Module files as
* expected by the WALA machinery.
*/
private Set<JarFileModule> getModuleFiles() {
Set<JarFileModule> result = HashSetFactory.make();
for (Iterator<JarFile> jars = applicationJarFiles.iterator(); jars.hasNext();) {
for (Iterator<JarFile> jars = applicationJarFiles.iterator(); jars.hasNext(); ) {
result.add(new JarFileModule(jars.next()));
}

Expand All @@ -162,11 +157,12 @@ private Set<JarFileModule> getModuleFiles() {

/**
* The heart of the analysis.
*
* @throws CancelException
* @throws IllegalArgumentException
*/
public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierarchyException, IllegalArgumentException,
CancelException {
public Set<IClass> gatherThreadEscapingClasses()
throws IOException, ClassHierarchyException, IllegalArgumentException, CancelException {

//
// set the application to analyze
Expand Down Expand Up @@ -226,7 +222,7 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
// 1) static fields
for (IClass cls : cha) {
Collection<IField> staticFields = cls.getDeclaredStaticFields();
for (Iterator<IField> sfs = staticFields.iterator(); sfs.hasNext();) {
for (Iterator<IField> sfs = staticFields.iterator(); sfs.hasNext(); ) {
IField sf = sfs.next();
if (sf.getFieldTypeReference().isReferenceType()) {
escapeAnalysisRoots.add(heapModel.getPointerKeyForStaticField(sf));
Expand All @@ -240,21 +236,21 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
// reachable from fields of types in these pointer keys, and all
// Thread objects must be constructed somewhere)
Collection<IClass> threads = cha.computeSubClasses(TypeReference.JavaLangThread);
for (Iterator<IClass> clss = threads.iterator(); clss.hasNext();) {
for (Iterator<IClass> clss = threads.iterator(); clss.hasNext(); ) {
IClass cls = clss.next();
for (Iterator<? extends IMethod> ms = cls.getDeclaredMethods().iterator(); ms.hasNext();) {
for (Iterator<? extends IMethod> ms = cls.getDeclaredMethods().iterator(); ms.hasNext(); ) {
IMethod m = ms.next();
if (m.isInit()) {
Set<CGNode> nodes = cg.getNodes(m.getReference());
for (Iterator<CGNode> ns = nodes.iterator(); ns.hasNext();) {
for (Iterator<CGNode> ns = nodes.iterator(); ns.hasNext(); ) {
CGNode n = ns.next();
escapeAnalysisRoots.add(heapModel.getPointerKeyForLocal(n, 1));
}
}
}
}

//
//
// compute escaping types: all types flowing to escaping roots and
// all types transitively reachable through their fields.
//
Expand All @@ -263,10 +259,10 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
//
// pass 1: get abstract objects (instance keys) for escaping locations
//
for (Iterator<PointerKey> rts = escapeAnalysisRoots.iterator(); rts.hasNext();) {
for (Iterator<PointerKey> rts = escapeAnalysisRoots.iterator(); rts.hasNext(); ) {
PointerKey root = rts.next();
OrdinalSet<InstanceKey> objects = pa.getPointsToSet(root);
for (Iterator<InstanceKey> objs = objects.iterator(); objs.hasNext();) {
for (Iterator<InstanceKey> objs = objects.iterator(); objs.hasNext(); ) {
InstanceKey obj = objs.next();
escapingInstanceKeys.add(obj);
}
Expand All @@ -278,15 +274,15 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
Set<InstanceKey> newKeys = HashSetFactory.make();
do {
newKeys.clear();
for (Iterator<InstanceKey> keys = escapingInstanceKeys.iterator(); keys.hasNext();) {
for (Iterator<InstanceKey> keys = escapingInstanceKeys.iterator(); keys.hasNext(); ) {
InstanceKey key = keys.next();
IClass type = key.getConcreteType();
if (type.isReferenceType()) {
if (type.isArrayClass()) {
if (((ArrayClass) type).getElementClass() != null) {
PointerKey fk = heapModel.getPointerKeyForArrayContents(key);
OrdinalSet<InstanceKey> fobjects = pa.getPointsToSet(fk);
for (Iterator<InstanceKey> fobjs = fobjects.iterator(); fobjs.hasNext();) {
for (Iterator<InstanceKey> fobjs = fobjects.iterator(); fobjs.hasNext(); ) {
InstanceKey fobj = fobjs.next();
if (!escapingInstanceKeys.contains(fobj)) {
newKeys.add(fobj);
Expand All @@ -295,12 +291,12 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
}
} else {
Collection<IField> fields = type.getAllInstanceFields();
for (Iterator<IField> fs = fields.iterator(); fs.hasNext();) {
for (Iterator<IField> fs = fields.iterator(); fs.hasNext(); ) {
IField f = fs.next();
if (f.getFieldTypeReference().isReferenceType()) {
PointerKey fk = heapModel.getPointerKeyForInstanceField(key, f);
OrdinalSet<InstanceKey> fobjects = pa.getPointsToSet(fk);
for (Iterator<InstanceKey> fobjs = fobjects.iterator(); fobjs.hasNext();) {
for (Iterator<InstanceKey> fobjs = fobjects.iterator(); fobjs.hasNext(); ) {
InstanceKey fobj = fobjs.next();
if (!escapingInstanceKeys.contains(fobj)) {
newKeys.add(fobj);
Expand All @@ -318,7 +314,7 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
// get set of types from set of instance keys
//
Set<IClass> escapingTypes = HashSetFactory.make();
for (Iterator<InstanceKey> keys = escapingInstanceKeys.iterator(); keys.hasNext();) {
for (Iterator<InstanceKey> keys = escapingInstanceKeys.iterator(); keys.hasNext(); ) {
InstanceKey key = keys.next();
escapingTypes.add(key.getConcreteType());
}
Expand All @@ -327,27 +323,31 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
}

/**
* This main program shows one example use of thread escape analysis: producing a set of fields to be monitored for a
* dynamic race detector. The idea is that any field might have a race with two exceptions: final fields do not have
* races since there are no writes to them, and volatile fields have atomic read and write semantics provided by the
* VM. Hence, this piece of code produces a list of all other fields.
* This main program shows one example use of thread escape analysis: producing a set of fields to
* be monitored for a dynamic race detector. The idea is that any field might have a race with two
* exceptions: final fields do not have races since there are no writes to them, and volatile
* fields have atomic read and write semantics provided by the VM. Hence, this piece of code
* produces a list of all other fields.
*
* @throws CancelException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws IOException, ClassHierarchyException, IllegalArgumentException, CancelException {
public static void main(String[] args)
throws IOException, ClassHierarchyException, IllegalArgumentException, CancelException {
String mainClassName = args[0];

Set<JarFile> jars = HashSetFactory.make();
for (int i = 1; i < args.length; i++) {
jars.add(new JarFile(args[i]));
}

Set<IClass> escapingTypes = (new SimpleThreadEscapeAnalysis(jars, mainClassName)).gatherThreadEscapingClasses();
Set<IClass> escapingTypes =
(new SimpleThreadEscapeAnalysis(jars, mainClassName)).gatherThreadEscapingClasses();

for (Iterator<IClass> types = escapingTypes.iterator(); types.hasNext();) {
for (Iterator<IClass> types = escapingTypes.iterator(); types.hasNext(); ) {
IClass cls = types.next();
if (!cls.isArrayClass()) {
for (Iterator<IField> fs = cls.getAllFields().iterator(); fs.hasNext();) {
for (Iterator<IField> fs = cls.getAllFields().iterator(); fs.hasNext(); ) {
IField f = fs.next();
if (!f.isVolatile() && !f.isFinal()) {
System.err.println(f.getReference());
Expand All @@ -356,5 +356,4 @@ public static void main(String[] args) throws IOException, ClassHierarchyExcepti
}
}
}

}
}
Loading

0 comments on commit fd1dbc4

Please sign in to comment.