【问题标题】:Java how to find number of times a method is calledJava如何查找方法被调用的次数
【发布时间】:2023-03-09 06:26:01
【问题描述】:

我需要知道一个类的每个方法被调用了多少次。如果是JDK源码需要分析的源码。
我使用了eclipse JDT。该程序的工作方式是通过 JDK Source 目录。它加载源并从中创建一个已编译的单元。然后我打印出所有完全限定的方法名称。即 package.class.method 名称。

现在我需要找出在其他源文件中调用 package.class.method 的次数。如果可以,请提供源代码。

这是我迄今为止编写的代码:

/*
 * 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());
            }
        }
    }

}

【问题讨论】:

  • 静态不可能。反射。将任务控制与飞行记录器结合使用。
  • 你到底要什么?这与 Eclipse 的“搜索 > 参考 > 工作区”相同吗?如果您指的是在编译过程中对某个方法进行的调用总数,则静态分析无法做到这一点 - 您必须运行代码并拦截调用。
  • 我有一个 Java 文件列表。我需要解析这些文件。获取这些类的所有类和所有方法。然后我需要确定每个方法被调用了多少次。注意:java 文件不是项目的一部分。
  • 你根本做不到,因为 Java 支持反射。
  • 你确定....?即使是 Eclipse JDT 也不行?

标签: java eclipse-jdt


【解决方案1】:

如果您确切知道要搜索的文本,您可以重定向控制台输出,您可以在 linux 上使用 grep 和 wc 命令实现,执行如下:

java mainclass | grep "searchpatterntomethodname" | wc -l

在 Windows 系统上,您有一个名为 findstr 的工具,它等同于 grep,find 等同于 wc。有了这个,您将过滤执行输出到搜索模式并计算行数,这必须与方法调用相同

【讨论】:

  • 这意味着在 for 循环中运行 100 次的方法调用显示为单个方法调用。不是很有用。
  • 如果您针对某个方法调用制作自定义日志(或控制台输出),并将其放置在您要监控的方法的开头/结尾处,您就可以实现您想要的。例如“开始审核的方法 XXX”并使用 grep 搜索该模式,您将获得对该方法的调用计数。我的意思是,在方法调用中写一个日志行,这样每次调用方法时都会得到一行
  • 虽然这适用于极其简单的情况,但它仍然不是一个好的解决方案。特别是因为提问者想分析JDK源代码。
猜你喜欢
  • 1970-01-01
  • 2016-06-30
  • 1970-01-01
  • 1970-01-01
  • 2020-05-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-06
  • 2021-11-04
相关资源
最近更新 更多