2

I need to find out how many times each method on a class is called. The source code that needs to be analyzed if the JDK source code.
I make use of the eclipse JDT. The way the program works is that one passes the JDK Source directory. It loads the source and creates a compiledunit from this. Then I print out all the fully qualified method names. i.e. package.class.method name.

Now I need to find out how many time package.class.method is called in the other source files. Please provide source code if you can.

Here's the code I have written thus far:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package methodcallcounter;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;

import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.TypeDeclaration;

public class MethodCallCounter {


    //use ASTParse to parse string
    public static CompilationUnit parse(String str, String fileName) {
        ASTParser parser = ASTParser.newParser(AST.JLS3);
        parser.setSource(str.toCharArray());
        parser.setResolveBindings(true);
        parser.setStatementsRecovery(true);
        parser.setBindingsRecovery(true);
        parser.setKind(ASTParser.K_COMPILATION_UNIT);
        parser.setUnitName(fileName);

        final CompilationUnit cu = (CompilationUnit) parser.createAST(null);

        return cu;
    }

    //read file content into a string
    public static String readFileToString(String filePath) throws IOException {
        StringBuilder fileData = new StringBuilder(1000);
        BufferedReader reader = new BufferedReader(new FileReader(filePath));

        char[] buf = new char[10];
        int numRead = 0;
        while ((numRead = reader.read(buf)) != -1) {
            String readData = String.valueOf(buf, 0, numRead);
            fileData.append(readData);
            buf = new char[1024];
        }

        reader.close();

        return fileData.toString();
    } 

    public static void listf(String directoryName, ArrayList<File> files) {
        File directory = new File(directoryName);

        // get all the files from a directory
        File[] fList = directory.listFiles();

        for (File file : fList) {
            if (file.isFile()) {
                files.add(file);

            } else if (file.isDirectory()) {
                listf(file.getAbsolutePath(), files);
            }

        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException, JavaModelException {

        ArrayList<File> al = new ArrayList<File>();
        ArrayList<CompilationUnit> cul = new ArrayList<CompilationUnit>();

        String dirPath = "C:\\Java\\SRC\\";
        listf(dirPath, al);

        for (File f : al) {
            cul.add(parse(readFileToString(f.getAbsolutePath()), f.getAbsolutePath()));
        }

        for (CompilationUnit c : cul) {
            try { 
                List<TypeDeclaration> types = c.types();

                for (TypeDeclaration object : types) {
                    if (object.getNodeType() == ASTNode.TYPE_DECLARATION){
                        String s = c.getPackage().getName().getFullyQualifiedName() + "." +
                            object.getName().getFullyQualifiedName();

                        MethodDeclaration[] meth = object.getMethods();
                        for (MethodDeclaration m : meth) {
                            //
                            System.out.println(s + " " +m.getName().getFullyQualifiedName());
                        }
                    } 
                } 

            } catch (NullPointerException ex) {
                System.out.println("Error : " + c.toString());
            }
        }
    }

}
Eminem
  • 7,206
  • 15
  • 53
  • 95
  • Not possible statically. Reflection. Use Mission Control with Flight Recorder. – Boris the Spider Nov 18 '16 at 12:29
  • What exactly are you asking for? Is this the same as the Eclipse 'Search > References > Workspace'? If you mean the total number of calls that would be made to a method during compilation of something you can't do that with static analysis - you have to run the code and intercept the calls. – greg-449 Nov 18 '16 at 13:33
  • I have a list of Java files. I need to parse those files. Get ALL the classes and ALL methods on those classes. Then I need to determine how many times each method is called. NOTE: The java files are NOT part of a project. – Eminem Nov 18 '16 at 14:40
  • You simply cannot do that, because Java supports reflection. – Boris the Spider Nov 18 '16 at 15:16
  • Are you sure....? Not even with the Eclipse JDT? – Eminem Nov 18 '16 at 18:21
  • Question still isn't clear: if you ask how many times a method IS CALLED, then you are asking for runtime information which cannot be provided by any static analysis. If you ask how many INVOCATIONS of a method exist in the code, then JDT's search engine would be a good match if you can setup a project context - otherwise you need to analyse the cross references by yourself (using an AST with resolved bindings). – Stephan Herrmann Nov 18 '16 at 22:06
  • Hi Stephan. Yes... you are quite correct in pointing out that how I asked my question is rather misleading. I do need the number of invocations of a method – Eminem Nov 19 '16 at 11:05
  • Is this what you are looking for: http://stackoverflow.com/questions/27278507/how-to-count-all-the-method-calls-in-jdk-using-eclipse-jdt/27351725#27351725 – Unni Kris Feb 28 '17 at 13:03

1 Answers1

-2

If you know exactly the text to be search, you can redirect console output you can achieve that on linux with grep and wc commands, executing it like this:

java mainclass | grep "searchpatterntomethodname" | wc -l

On windows systems you have a tool called findstr equivalent to grep and find as equivalent of wc. With this you'll filter the execution output to the search pattern and count number of lines, that must be the same as the method calls

Francisco Valle
  • 613
  • 10
  • 10
  • 1
    This would mean that a method call in a for loop that runs `100` times shows up as a single method call. Not very useful. – Kayaman Nov 18 '16 at 12:47
  • If you make a custom log (or console output) specific to a method call, and place it at the beggining / end of the method you want to monitor, you can achieve what you want. For example "Start audited method XXX" and you search that pattern with grep, you'll get the count of calls to the method. I mean, write a log line inside the method call, so youll get a line each time the method is called – Francisco Valle Nov 18 '16 at 13:11
  • 1
    While that would work for extremely simple cases, it's still not a good solution. Especially since the asker wants to analyze the JDK source code. – Kayaman Nov 18 '16 at 13:27