views:

639

answers:

10

I am working on a library where we want to determine how much of our library is being used. I.E. we want to know how many methods in our library are public, but never being called.

Goal: Static Analysis Determine how many lines of code call each public method in package A in the current project. If the number of calls is zero, the method should be reported as such.

A: 

Here's are a few lists of Java code coverage tools. I haven't used any of these personally, but it might get you started:

Andy White
The problem with code coverage tools is that they work at run-time, so that you might miss "rare" code paths.
Thilo
+3  A: 

Not exactly what you are looking for, but:

Something similar be done with code coverage tools (like Cobertura). They do not do static inspection of the source code, but instrument the bytecode to gather metrics at runtime. Of course, you need to drive the application in a way that exercises all usage pattern, and might miss the rarer code paths.

On the static analysis front, maybe these tools can help you (the Apache project uses them to check for API compatibility for new releases, seems like that task is somewhat related to what you are trying to do):

  • Clirr is a tool that checks Java libraries for binary and source compatibility with older releases. Basically you give it two sets of jar files and Clirr dumps out a list of changes in the public api.
  • JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.
Thilo
+1  A: 

I don't think you are able to measure how "often" a class or a function is needed.
There are some simple questions:

  • What defines, if a usage statistic of your game library is "normal" or an "outlier"? Is it wrong to kill yourself in the game too often? You would use the "killScreen" class more frequently like a good gamer.
  • What defines "much"? Time or usage count? POJOs will consume rare time, but are used pretty frequently.

Conclusion:
I don't know what you are trying to accomplish.
If you want to display your code dependencies, there are other tools for doing this. If you're trying to measure your code execution, there are profiler or benchmarks for Java. If you are a statistic geek, you'll be happy with RapidMiner ;)

Good luck with that!

furtelwart
+1  A: 

I would suggest JDepend shows you the dependencies between packages and classes, excellent to find cyclic dependencies! http://clarkware.com/software/JDepend.html (it has an eclipse plugin: http://andrei.gmxhome.de/jdepend4eclipse/

and also PMD for other metrics http://pmd.sourceforge.net/

silmx
+9  A: 

I belive you are looking for this eclipse plugin --> UCDetector

From the documentation (pay notice to second bullet point)

  • Unnecessary (dead) code
  • Code where the visibility could be changed to protected, default or private
  • Methods of fields, which can be final

On Larger scale, if you want to do Object Level Static Analysis, look at this tool from IBM -->Structural Analysis for Java. It is really helpful for object analysis of libraries, APIs, etc.

peacefulfire
+3  A: 

Client use of reflective calls is one hole in static analysis to consider. As there's no way to know for sure that a particular method isn't being called via some bizarre reflection scheme. So, maybe a combination of runtime and static analysis might be best.

ShabbyDoo
A: 

Proguard may be an option too (http://proguard.sourceforge.net/):

"Some uses of ProGuard are:

  • ...
  • Listing dead code, so it can be removed from the source code.
  • ... "

See also http://proguard.sourceforge.net/manual/examples.html#deadcode

Bert F
A: 

You could write your own utility for that (within an hours after reading this) using the ASM bytecode analysis library (http://asm.ow2.org). You'll need to implement a ClassVisitor and a MethodVisitor. You'll use a ClassReader to parse the class files in your library.

  • Your ClassVisitor's visitMethod(..) will be called for each declared method.
  • Your MethodVisitor's visitMethodInsn(..) will be called for each called method.

Maintain a Map to do the counting. The keys represent the methods (see below). Here's some code:

class MyClassVisitor {
    // ...
    public void visit(int version, int access, String name, ...) {
        this.className = name;
    }
    public MethodVisitor visitMethod(int access, String name, String desc, ...):
        String key = className + "." + name + "#" + desc;
        if (!map.containsKey() {
            map.put(key, 0);
        }
        return new MyMethodVisitor(map);
    }
    // ...
}

void class MyMethodVisitor {
    // ...
    public visitMethodInsn(int opcode, String name, String owner, String desc, ...) {
        String key = owner + "." + name + "#" + desc;
        if (!map.containsKey() {
            map.put(key, 0);
        }
        map.put(key, map.get(key) + 1);
    }
    // ...
}

Basically that's it. Your're starting the show with something like this:

Map<String,Integer> map = new HashMap<String,Integer>();
for (File classFile : my library) {
    InputStream input = new FileInputStream(classFile);
    new ClassReader(input).accept(new MyClassVisitor(map), 0);
    input.close();
}
for (Map.Entry<String,Integer> entry : map.entrySet()) {
    if (entry.getValue() == 0) {
        System.out.println("Unused method: " + entry.getKey());
    }
}

Enjoy!

chris
If method A calls method B, method B will get marked as "used", even if method A isn't used, so this isn't quite the right way to count. You need to take a transitive closure on "used".
Ira Baxter
+1  A: 

IntelliJ has a tool to detect methods, fields, class which can have more restricted modifiers. It also a has a quick fix to apply these changes which can save you a lot of work as well. If you don't want to pay for it, you can get the 30-day eval license which is more than enough time to change your code, its not something your should need to do very often.

BTW: IntelliJ has about 650 code inspections to improve code quality, about half has automatic fixes so I suggest spend a couple of day using it to refactor/tidy up your code.

Peter Lawrey
+1  A: 

Please take a look at Dead Code Detector. It claims to do just what you are looking for: finding unused code using static analysis.

Kees de Kooter