Skip to content

Changed JCallGraph to be able to process not only JAR files, but also… #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 46 additions & 25 deletions src/main/java/gr/gousiosg/javacg/stat/JCallGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,44 +37,65 @@
import org.apache.bcel.classfile.ClassParser;

/**
* Constructs a callgraph out of a JAR archive. Can combine multiple archives
* into a single call graph.
* Constructs a callgraph out of a set of directories, classes and JAR archives.
* Can combine multiple archives into a single call graph.
*
* @author Georgios Gousios <gousiosg@gmail.com>
*
*/
public class JCallGraph {

public static void main(String[] args) {
ClassParser cp;
try {
for (String arg : args) {
public static void processClass(String class_name) throws IOException {
ClassParser cp = new ClassParser(class_name);
ClassVisitor visitor = new ClassVisitor(cp.parse());
visitor.start();
}

public static void processClass(String jar_name, String class_name) throws IOException {
ClassParser cp = new ClassParser(jar_name,class_name);
ClassVisitor visitor = new ClassVisitor(cp.parse());
visitor.start();
}

public static void processJar(JarFile jar) throws IOException {
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.isDirectory())
continue;

File f = new File(arg);

if (!f.exists()) {
System.err.println("Jar file " + arg + " does not exist");
}

JarFile jar = new JarFile(f);
if (!entry.getName().endsWith(".class"))
continue;

Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.isDirectory())
continue;
processClass(jar.getName(),entry.getName());
}
}

if (!entry.getName().endsWith(".class"))
continue;
public static void processFile(File file) {
try {
if (!file.exists())
System.err.println("File " + file.getName() + " does not exist");

cp = new ClassParser(arg,entry.getName());
ClassVisitor visitor = new ClassVisitor(cp.parse());
visitor.start();
}
else if (file.isDirectory()) {
for (File dfile : file.listFiles())
processFile(dfile);
}

else if (file.getName().endsWith(".jar"))
processJar(new JarFile(file));

else if (file.getName().endsWith(".class"))
processClass(file.getAbsolutePath());

} catch (IOException e) {
System.err.println("Error while processing jar: " + e.getMessage());
System.err.println("Error while processing file: " + e.getMessage());
e.printStackTrace();
}
}

public static void main(String[] args) {
for (String arg : args) {
processFile(new File(arg));
}
}
}
12 changes: 6 additions & 6 deletions src/main/java/gr/gousiosg/javacg/stat/MethodVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public MethodVisitor(MethodGen m, JavaClass jc) {
visitedClass = jc;
mg = m;
cp = mg.getConstantPool();
format = "M:" + visitedClass.getClassName() + ":" + mg.getName() + "(" + argumentList(mg.getArgumentTypes()) + ")"
format = "M:" + visitedClass.getClassName() + ":" + mg.getName() + "(" + argumentList(mg.getArgumentTypes()) + "):%d"
+ " " + "(%s)%s:%s(%s)";
}

Expand Down Expand Up @@ -84,27 +84,27 @@ private boolean visitInstruction(Instruction i) {

@Override
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL i) {
System.out.println(String.format(format,"M",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
System.out.println(String.format(format,i.getIndex(),"M",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
}

@Override
public void visitINVOKEINTERFACE(INVOKEINTERFACE i) {
System.out.println(String.format(format,"I",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
System.out.println(String.format(format,i.getIndex(),"I",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
}

@Override
public void visitINVOKESPECIAL(INVOKESPECIAL i) {
System.out.println(String.format(format,"O",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
System.out.println(String.format(format,i.getIndex(),"O",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
}

@Override
public void visitINVOKESTATIC(INVOKESTATIC i) {
System.out.println(String.format(format,"S",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
System.out.println(String.format(format,i.getIndex(),"S",i.getReferenceType(cp),i.getMethodName(cp),argumentList(i.getArgumentTypes(cp))));
}

@Override
public void visitINVOKEDYNAMIC(INVOKEDYNAMIC i) {
System.out.println(String.format(format,"D",i.getType(cp),i.getMethodName(cp),
System.out.println(String.format(format,i.getIndex(),"D",i.getType(cp),i.getMethodName(cp),
argumentList(i.getArgumentTypes(cp))));
}
}