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;
 }
Category >> Java Development Tools (JDT)  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>

  1. ShinyGirl on 2013-4-21

    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 ()

  2. ryanlr on 2013-4-23

    Can you post your code here?

  3. ShinyGirl on 2013-4-23

    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 ^_^

  4. ShinyGirl on 2013-5-2

    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

  5. ryanlr on 2013-5-2

    I don’t know. Maybe you can post this question on stackoverflow.

  6. Kadir on 2015-1-13

    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?

  7. bniyaseen on 2015-2-28

    can you post the second way :
    Use the eclipse ast visitor

  8. Danilo Batista on 2016-2-4

    I have the same problem. You could solve?
    thank you

  9. s3 on 2016-6-22

    I want to get the reference on code which is not in compiling stage.

  10. s3 on 2016-6-22

    I want to get the reference on code which is not in compiling stage
    Can anyone suggest the way?

  11. Jiří Kačírek on 2017-3-31

    Why did you not mentioned where your dependencies come from???

Leave a comment

*