Skip to content

Commit c05925e

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents c280f8a + bd61ce5 commit c05925e

File tree

6 files changed

+75
-66
lines changed

6 files changed

+75
-66
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ bin/
1111
.project
1212
.settings/
1313

14+
# intellij
15+
.idea/
16+
*.iml
17+

README.md

+26-22
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ A suite of programs for generating static and dynamic call graphs in Java.
1212

1313
#### Compile
1414

15-
The java-callgraph package is build with maven. Install maven and do:
15+
The java-callgraph package is build with maven. Install maven and do:
1616

17-
<code>
17+
```
1818
mvn install
19-
</code>
19+
```
2020

2121
This will produce a `target` directory with the following three jars:
2222
- javacg-0.1-SNAPSHOT.jar: This is the standard maven packaged jar with static and dynamic call graph generator classes
@@ -31,39 +31,42 @@ Instructions for running the callgraph generators
3131

3232
`javacg-static` accepts as arguments the jars to analyze.
3333

34-
<code>
34+
```
3535
java -jar javacg-0.1-SNAPSHOT-static.jar lib1.jar lib2.jar...
36-
</code>
36+
```
3737

3838
`javacg-static` produces combined output in the following format:
3939

4040
###### For methods
4141

42-
<code>
43-
M:class1:<method1> (typeofcall)class2:<method2>
44-
</code>
42+
```
43+
M:class1:<method1>(arg_types) (typeofcall)class2:<method2>(arg_types)
44+
```
4545

4646
The line means that `method1` of `class1` called `method2` of `class2`.
4747
The type of call can have one of the following values (refer to
48-
the [JVM specification](http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc6.html)
49-
for the meaning of the calls):
48+
the [JVM specification](http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc6.html)
49+
for the meaning of the calls):
5050

5151
* `M` for `invokevirtual` calls
5252
* `I` for `invokeinterface` calls
5353
* `O` for `invokespecial` calls
5454
* `S` for `invokestatic` calls
55+
* `D` for `invokedynamic` calls
56+
57+
For `invokedynamic` calls, it is not possible to infer the argument types.
5558

5659
###### For classes
5760

58-
<code>
61+
```
5962
C:class1 class2
60-
</code>
63+
```
6164

6265
This means that some method(s) in `class1` called some method(s) in `class2`.
6366

6467
##### Dynamic
6568

66-
`javacg-dynamic` uses
69+
`javacg-dynamic` uses
6770
[javassist](http://www.csg.is.titech.ac.jp/~chiba/javassist/) to insert probes
6871
at method entry and exit points. To be able to analyze a class `javassist` must
6972
resolve all dependent classes at instrumentation time. To do so, it reads
@@ -81,7 +84,9 @@ entries), `javacg-dynamic` includes support for restricting the set of classes
8184
to be instrumented through include and exclude statements. The options are
8285
appended to the `-javaagent` argument and has the following format
8386

84-
<code>-javaagent:javacg-dycg-agent.jar="incl=mylib.*,mylib2.*,java.nio.*;excl=java.nio.charset.*"</code>
87+
```
88+
-javaagent:javacg-dycg-agent.jar="incl=mylib.*,mylib2.*,java.nio.*;excl=java.nio.charset.*"
89+
```
8590

8691
The example above will instrument all classes under the the `mylib`, `mylib2` and
8792
`java.nio` namespaces, except those that fall under the `java.nio.charset` namespace.
@@ -90,7 +95,7 @@ The example above will instrument all classes under the the `mylib`, `mylib2` an
9095
java
9196
-Xbootclasspath:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar:mylib.jar
9297
-javaagent:javacg-0.1-SNAPSHOT-dycg-agent.jar="incl=mylib.*;"
93-
-classpath mylib.jar mylib.Mainclass
98+
-classpath mylib.jar mylib.Mainclass
9499
```
95100

96101
`javacg-dynamic` produces two kinds of output. On the standard output, it
@@ -110,16 +115,16 @@ a poor man's profiler. The format is the following:
110115

111116
The output line starts with a `<` or `>` depending on whether it is a method
112117
entry or exit. It then writes the stack depth, thread id and the class and
113-
method name, followed by a timestamp. The provided `process_trace.rb`
118+
method name, followed by a timestamp. The provided `process_trace.rb`
114119
script processes the callgraph output to generate total time per method
115-
information.
120+
information.
116121

117122
#### Examples
118123

119-
The following examples instrument the
120-
[Dacapo benchmark suite](http://dacapobench.org/) to produce dynamic call graphs.
124+
The following examples instrument the
125+
[Dacapo benchmark suite](http://dacapobench.org/) to produce dynamic call graphs.
121126
The Dacapo benchmarks come in a single big jar archive that contains all dependency
122-
libraries. To build the boot class path required for the javacg-dyn program,
127+
libraries. To build the boot class path required for the javacg-dyn program,
123128
extract the `dacapo.jar` to a directory: all the required libraries can be found
124129
in the `jar` directory.
125130

@@ -167,7 +172,7 @@ org.apache.lucene.analysis.Token:termLength org.apache.lucene.analysis.Token:ini
167172

168173
* The static call graph generator does not account for methods invoked via
169174
reflection.
170-
* The dynamic call graph generator will not work reliably (or at all) for
175+
* The dynamic call graph generator will not work reliably (or at all) for
171176
multithreaded programs
172177
* The dynamic call graph generator does not handle exceptions very well, so some
173178
methods might appear as having never returned
@@ -179,4 +184,3 @@ Georgios Gousios <gousiosg@gmail.com>
179184
#### License
180185

181186
[2-clause BSD](http://www.opensource.org/licenses/bsd-license.php)
182-

pom.xml

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<dependency>
1818
<groupId>org.apache.bcel</groupId>
1919
<artifactId>bcel</artifactId>
20-
<version>5.2</version>
20+
<version>6.0</version>
2121
<scope>provided</scope>
2222
</dependency>
2323
<dependency>
@@ -32,7 +32,7 @@
3232
<plugin>
3333
<groupId>org.apache.maven.plugins</groupId>
3434
<artifactId>maven-assembly-plugin</artifactId>
35-
<version>2.2.1</version>
35+
<version>3.0.0</version>
3636
<configuration>
3737
<descriptors>
3838
<descriptor>assembly-dyn.xml</descriptor>
@@ -58,11 +58,11 @@
5858
</plugin>
5959
<plugin>
6060
<artifactId>maven-compiler-plugin</artifactId>
61-
<version>2.3.2</version>
61+
<version>3.6.1</version>
6262
<configuration>
6363
<optimize>false</optimize>
64-
<source>1.6</source>
65-
<target>1.6</target>
64+
<source>1.8</source>
65+
<target>1.8</target>
6666
</configuration>
6767
</plugin>
6868
</plugins>

src/main/java/gr/gousiosg/javacg/dyn/Instrumenter.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646

4747
public class Instrumenter implements ClassFileTransformer {
4848

49-
static List<Pattern> pkgIncl = new ArrayList<Pattern>();
50-
static List<Pattern> pkgExcl = new ArrayList<Pattern>();
49+
static List<Pattern> pkgIncl = new ArrayList<>();
50+
static List<Pattern> pkgExcl = new ArrayList<>();
5151

5252
public static void premain(String argument, Instrumentation instrumentation) {
5353

@@ -63,14 +63,14 @@ public static void premain(String argument, Instrumentation instrumentation) {
6363
String[] tokens = argument.split(";");
6464

6565
if (tokens.length < 1) {
66-
err("Missing delimeter ;");
66+
err("Missing delimiter ;");
6767
return;
6868
}
6969

7070
for (String token : tokens) {
7171
String[] args = token.split("=");
7272
if (args.length < 2) {
73-
err("Missing argument delimeter =:" + token);
73+
err("Missing argument delimiter =:" + token);
7474
return;
7575
}
7676

@@ -118,7 +118,7 @@ public byte[] transform(ClassLoader loader, String className, Class clazz,
118118
for (Pattern p : pkgExcl) {
119119
Matcher m = p.matcher(name);
120120
if (m.matches()) {
121-
err("Not enhansing class: " + name);
121+
err("Skipping class: " + name);
122122
enhanceClass = false;
123123
break;
124124
}

src/main/java/gr/gousiosg/javacg/dyn/MethodStack.java

+10-14
Original file line numberDiff line numberDiff line change
@@ -33,40 +33,36 @@
3333
import java.io.IOException;
3434
import java.util.ArrayList;
3535
import java.util.Collections;
36-
import java.util.Comparator;
3736
import java.util.HashMap;
3837
import java.util.List;
3938
import java.util.Map;
4039
import java.util.Stack;
4140

4241
public class MethodStack {
4342

44-
private static Stack<String> stack = new Stack<String>();
45-
private static Map<Pair<String, String>, Integer> callgraph = new HashMap<Pair<String,String>, Integer>();
43+
private static Stack<String> stack = new Stack<>();
44+
private static Map<Pair<String, String>, Integer> callgraph = new HashMap<>();
4645
static FileWriter fw;
4746
static StringBuffer sb;
4847
static long threadid = -1L;
49-
48+
5049
static {
5150
Runtime.getRuntime().addShutdownHook(new Thread() {
5251
public void run() {
5352
try {
5453
fw.close();
5554
} catch (IOException e) {
56-
// TODO Auto-generated catch block
5755
e.printStackTrace();
5856
}
5957
//Sort by number of calls
60-
List<Pair<String, String>> keys = new ArrayList<Pair<String, String>>();
58+
List<Pair<String, String>> keys = new ArrayList<>();
6159
keys.addAll(callgraph.keySet());
62-
Collections.sort(keys, new Comparator<Object>() {
63-
public int compare(Object o1, Object o2) {
64-
Integer v1 = callgraph.get(o1);
65-
Integer v2 = callgraph.get(o2);
66-
return v1.compareTo(v2);
67-
}
60+
Collections.sort(keys, (o1, o2) -> {
61+
Integer v1 = callgraph.get(o1);
62+
Integer v2 = callgraph.get(o2);
63+
return v1.compareTo(v2);
6864
});
69-
65+
7066
for (Pair<String, String> key : keys) {
7167
System.out.println(key + " " + callgraph.get(key));
7268
}
@@ -91,7 +87,7 @@ public static void push(String callname, Object [] argM) throws IOException {//
9187
return;
9288

9389
if (!stack.isEmpty()) {
94-
Pair<String, String> p = new Pair<String, String>(stack.peek(), callname);
90+
Pair<String, String> p = new Pair<>(stack.peek(), callname);
9591
if (callgraph.containsKey(p))
9692
callgraph.put(p, callgraph.get(p) + 1);
9793
else

src/main/java/gr/gousiosg/javacg/stat/MethodVisitor.java

+25-20
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,7 @@
2929
package gr.gousiosg.javacg.stat;
3030

3131
import org.apache.bcel.classfile.JavaClass;
32-
import org.apache.bcel.generic.ConstantPoolGen;
33-
import org.apache.bcel.generic.ConstantPushInstruction;
34-
import org.apache.bcel.generic.EmptyVisitor;
35-
import org.apache.bcel.generic.INVOKEINTERFACE;
36-
import org.apache.bcel.generic.INVOKESPECIAL;
37-
import org.apache.bcel.generic.INVOKESTATIC;
38-
import org.apache.bcel.generic.INVOKEVIRTUAL;
39-
import org.apache.bcel.generic.Instruction;
40-
import org.apache.bcel.generic.InstructionConstants;
41-
import org.apache.bcel.generic.InstructionHandle;
42-
import org.apache.bcel.generic.MethodGen;
43-
import org.apache.bcel.generic.ReturnInstruction;
32+
import org.apache.bcel.generic.*;
4433

4534
/**
4635
* The simplest of method visitors, prints any invoked method
@@ -59,8 +48,19 @@ public MethodVisitor(MethodGen m, JavaClass jc) {
5948
visitedClass = jc;
6049
mg = m;
6150
cp = mg.getConstantPool();
62-
format = "M:" + visitedClass.getClassName() + ":" + mg.getName()
63-
+ " " + "(%s)%s:%s";
51+
format = "M:" + visitedClass.getClassName() + ":" + mg.getName() + "(" + argumentList(mg.getArgumentTypes()) + ")"
52+
+ " " + "(%s)%s:%s(%s)";
53+
}
54+
55+
private String argumentList(Type[] arguments) {
56+
StringBuilder sb = new StringBuilder();
57+
for (int i = 0; i < arguments.length; i++) {
58+
if (i != 0) {
59+
sb.append(",");
60+
}
61+
sb.append(arguments[i].toString());
62+
}
63+
return sb.toString();
6464
}
6565

6666
public void start() {
@@ -77,29 +77,34 @@ public void start() {
7777

7878
private boolean visitInstruction(Instruction i) {
7979
short opcode = i.getOpcode();
80-
81-
return ((InstructionConstants.INSTRUCTIONS[opcode] != null)
80+
return ((InstructionConst.getInstruction(opcode) != null)
8281
&& !(i instanceof ConstantPushInstruction)
8382
&& !(i instanceof ReturnInstruction));
8483
}
8584

8685
@Override
8786
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL i) {
88-
System.out.println(String.format(format,"M",i.getReferenceType(cp),i.getMethodName(cp)));
87+
System.out.println(String.format(format,"M",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
8988
}
9089

9190
@Override
9291
public void visitINVOKEINTERFACE(INVOKEINTERFACE i) {
93-
System.out.println(String.format(format,"I",i.getReferenceType(cp),i.getMethodName(cp)));
92+
System.out.println(String.format(format,"I",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
9493
}
9594

9695
@Override
9796
public void visitINVOKESPECIAL(INVOKESPECIAL i) {
98-
System.out.println(String.format(format,"O",i.getReferenceType(cp),i.getMethodName(cp)));
97+
System.out.println(String.format(format,"O",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
9998
}
10099

101100
@Override
102101
public void visitINVOKESTATIC(INVOKESTATIC i) {
103-
System.out.println(String.format(format,"S",i.getReferenceType(cp),i.getMethodName(cp)));
102+
System.out.println(String.format(format,"S",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
103+
}
104+
105+
@Override
106+
public void visitINVOKEDYNAMIC(INVOKEDYNAMIC i) {
107+
System.out.println(String.format(format,"D",i.getType(cp),i.getMethodName(cp),
108+
argumentList(i.getArgumentTypes(cp))));
104109
}
105110
}

0 commit comments

Comments
 (0)