Java: Find all callers of a method – get all methods that call a particular method

This tutorial belongs to Eclipse JDT Tutorial Series.

I will explore how we can compute fan in i.e. find all the methods that call a particular method (all callers of a method).

In Eclipse, one can right click on a method and choose “open call hierarchy” and eclipse shows all the methods that call the selected method and all the methods that are called from the selected method (callers and callees of the selected method).

We can programtically find callers and callees and I will explain how I have done it.

There are a couple of different ways that I know:

  1. Use the eclipse JDT internal classes : these are the same classes used by eclipse to show the callers and callees of a method
  2. Use the eclipse ast visitor

In this post, I will discuss how we can use the eclipse JDT internal classes to find callers and callees of a method.

Firstly, import the following classes (as you can see they are in an “internal” package!)

import org.eclipse.jdt.internal.corext.callhierarchy.CallHierarchy;
import org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper;

Write a methodgetCallersOf that takes the selected method as an input [IMethod]. This will be your API type method, you should call this method from your program for any method whose callers you wish to find.

The crucial part of the code is to first get the default CallHierarchy object, use this CallHierarchy object to get the caller-roots of the input IMethod, and for each method-wrapper object that is returned, invoke the getCalls method. getCalls in turn returns an array of MethodWrapper objects and these are the actual callers. From each MethodWrapper object, we can get a corresponding IMethod.

 
public HashSet<IMethod> getCallersOf(IMethod m) {
 
 CallHierarchy callHierarchy = CallHierarchy.getDefault();
 
 IMember[] members = {m};
 
 MethodWrapper[] methodWrappers = callHierarchy.getCallerRoots(members);
  HashSet<IMethod> callers = new HashSet<IMethod>();
  for (MethodWrapper mw : methodWrappers) {
    MethodWrapper[] mw2 = mw.getCalls(new NullProgressMonitor());
    HashSet<IMethod> temp = getIMethods(mw2);
    callers.addAll(temp);    
   }
 
return callers;
}
 
 HashSet<IMethod> getIMethods(MethodWrapper[] methodWrappers) {
  HashSet<IMethod> c = new HashSet<IMethod>(); 
  for (MethodWrapper m : methodWrappers) {
   IMethod im = getIMethodFromMethodWrapper(m);
   if (im != null) {
    c.add(im);
   }
  }
  return c;
 }
 
 IMethod getIMethodFromMethodWrapper(MethodWrapper m) {
  try {
   IMember im = m.getMember();
   if (im.getElementType() == IJavaElement.METHOD) {
    return (IMethod)m.getMember();
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
  return null;
 }

13 thoughts on “Java: Find all callers of a method – get all methods that call a particular method”

  1. https://uploads.disquscdn.com/images/0454ff7885cb0771470fcf4eae3ad819645c1f84473b43558fcbe46324db859d.png

    But after doing all, one will ger ‘Workspace Closed’ error. Any pointer appreciated.

    Exception in thread “main” java.lang.IllegalStateException: Workspace is closed.
    at org.eclipse.core.resources.ResourcesPlugin.getWorkspace(ResourcesPlugin.java:412)
    at util.FindAllMethodInWorkspace.processRootDirectory(FindAllMethodInWorkspace.java:32)
    at util.FindAllMethodInWorkspace.main(FindAllMethodInWorkspace.java:20)

  2. Thank you for your helpful article .
    However , My project is written in J2SE 1.3 version and i cannot change the version because of hardware reasons.Do you have any idea or any technique for finding all callers of a method in java 1.3 version.Could you please to help me answer the following question?

  3. hi,
    i’m trying to analyse the JHotDraw project to calculate the fan in metric, but i’m getting a java.lang.nullPointerException @ this line MethodWrapper[] mw2 = mw.getCalls(new NullProgressMonitor());

    org.eclipse.e4.core.di.InjectionException: java.lang.NullPointerException
    at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:63)
    at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:231)
    at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:212)
    at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:131)
    at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.executeHandler(HandlerServiceImpl.java:171)
    at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem.executeItem(HandledContributionItem.java:831)
    at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem.handleWidgetSelection(HandledContributionItem.java:724)
    at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem.access$7(HandledContributionItem.java:708)
    at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem$4.handleEvent(HandledContributionItem.java:647)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4169)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3758)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1053)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:942)
    at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:86)
    at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:588)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:543)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
    at org.eclipse.equinox.launcher.Main.main(Main.java:1414)
    Caused by: java.lang.NullPointerException
    at org.eclipse.jdt.internal.core.search.matching.ClasspathSourceDirectory.directoryTable(ClasspathSourceDirectory.java:44)
    at org.eclipse.jdt.internal.core.search.matching.ClasspathSourceDirectory.findClass(ClasspathSourceDirectory.java:84)
    at org.eclipse.jdt.internal.core.search.matching.JavaSearchNameEnvironment.findClass(JavaSearchNameEnvironment.java:146)
    at org.eclipse.jdt.internal.core.search.matching.JavaSearchNameEnvironment.findType(JavaSearchNameEnvironment.java:185)
    at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.askForType(LookupEnvironment.java:145)
    at org.eclipse.jdt.internal.compiler.lookup.PackageBinding.getTypeOrPackage(PackageBinding.java:197)
    at org.eclipse.jdt.internal.compiler.lookup.Scope.getTypeOrPackage(Scope.java:2795)
    at org.eclipse.jdt.internal.compiler.lookup.Scope.getType(Scope.java:2513)
    at org.eclipse.jdt.internal.core.search.matching.MatchLocator.getType(MatchLocator.java:899)
    at org.eclipse.jdt.internal.core.search.matching.MatchLocator.getMethodBinding0(MatchLocator.java:955)
    at org.eclipse.jdt.internal.core.search.matching.MatchLocator.getMethodBinding(MatchLocator.java:907)
    at org.eclipse.jdt.internal.core.search.matching.MethodLocator.matchMethod(MethodLocator.java:327)
    at org.eclipse.jdt.internal.core.search.matching.MethodLocator.resolveLevel(MethodLocator.java:664)
    at org.eclipse.jdt.internal.core.search.matching.ClassFileMatchLocator.locateMatches(ClassFileMatchLocator.java:209)
    at org.eclipse.jdt.internal.core.search.matching.MatchLocator.process(MatchLocator.java:1697)
    at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1141)
    at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1182)
    at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1299)
    at org.eclipse.jdt.internal.core.search.JavaSearchParticipant.locateMatches(JavaSearchParticipant.java:95)
    at org.eclipse.jdt.internal.core.search.BasicSearchEngine.findMatches(BasicSearchEngine.java:231)
    at org.eclipse.jdt.internal.core.search.BasicSearchEngine.search(BasicSearchEngine.java:515)
    at org.eclipse.jdt.core.search.SearchEngine.search(SearchEngine.java:584)
    at org.eclipse.jdt.internal.corext.callhierarchy.CallerMethodWrapper.findChildren(CallerMethodWrapper.java:155)
    at org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper.performSearch(MethodWrapper.java:301)
    at org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper.doFindChildren(MethodWrapper.java:232)
    at org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper.getCalls(MethodWrapper.java:84)
    at projet.aspectm.plug.handler.ExtractHandler.getCallersOf(ExtractHandler.java:206)
    at projet.aspectm.plug.handler.ExtractHandler.printIMethodDetails(ExtractHandler.java:174)
    at projet.aspectm.plug.handler.ExtractHandler.printIMethods(ExtractHandler.java:121)
    at projet.aspectm.plug.handler.ExtractHandler.printCompilationUnitDetails(ExtractHandler.java:137)
    at projet.aspectm.plug.handler.ExtractHandler.printICompilationUnitInfo(ExtractHandler.java:112)
    at projet.aspectm.plug.handler.ExtractHandler.printPackageInfos(ExtractHandler.java:99)
    at projet.aspectm.plug.handler.ExtractHandler.execute(ExtractHandler.java:68)
    at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:290)
    at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:76)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:56)
    … 34 more

  4. I used reflection to get all classes and methods from a given java project
    with the method : class.getDeclaredMethods();

    I want to get the callers of each method in this list or if I can do the same thing with the API org.eclipse.jdt.core or if I can find an IMethod from the method name (string) to finally use the code you proposed

    thank you very much for your reply ^_^

  5. how I can use this code if I have a list of methods (Method [] and not IMethod []) because this code generates me the following error: Exception in thread “main” java.lang.Error: Unresolved compilation problem:
    The method getCallersOf(IMethod) in the type TestingCalls is not applicable for the arguments ()

Leave a Comment