Java reflection: finding method usage in custom abstractprocessor
I am a novice reflection Is there any way to detect where a particular method is called? For example:
public class MyClass {
public static void method(){
//DO SOMETHING
}
}
public class Test {
public test(){
MyClass.method();
}
}
public class MyProcessor extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations,RoundEnvironment roundEnv) {
Method method = MyClass.class.getDeclaredMethod("method");
Class classWhereMethodIsInvoked = obtainClassWhereMethodIsInvoked(method);
}
public Class obtainClassWhereMethodIsInvoked(Method method) {
//here I want to search one class that invoke that method,in this case Test.class
}
}
Is that possible, or am I crazy?
Solution
Yes, if you really want it to work, you can use classloader to search the classpath and scan the method name through all class files The following is a very simple example to illustrate its feasibility In the following example, I find that the "println" method is used in this class Essentially, you can extend the scope of one file in the example to all class files
public class SearchClasses {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException {
// InputStream is = SearchClasses.class.getClassLoader().getResourceAsStream("resources.SearchClasses.class");
InputStream is = new FileInputStream(new File("build/classes/resources/SearchClasses.class"));
boolean found = false;
Scanner scanner = new Scanner(is);
while (scanner.hasNext()) {
if (scanner.nextLine().contains("println")) {
System.out.print("println found");
found = true;
break;
}
}
if (!found) {
System.out.print("println NOT found");
}
}
public static void testMethod() {
System.out.println("testing");
}
}
In my IDE, I have to use FileInputStream to access the class file I am searching for However, if you are searching for jar files, you can use classloader You need a mechanism to search all Classpaths... It's not impossible, but I'll stay for simplicity
Editor: This is trying to make it work completely Search all files in the classpath for your method
public class SearchClasses {
/**
* @param args the command line arguments
* @throws java.io.FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException,IOException {
printAllFileWithMethod("println");
}
public static void printAllFileWithMethod(String methodName) throws FileNotFoundException,IOException {
Enumeration<URL> roots = SearchClasses.class.getClassLoader().getResources("");
List<File> allClassFiles = new ArrayList<>();
while (roots.hasMoreElements()) {
File root = new File(roots.nextElement().getPath());
allClassFiles.addAll(getFilesInDirectoryWithSuffix(root,"class"));
}
for (File classFile : allClassFiles) {
InputStream is = new FileInputStream(classFile);
boolean found = false;
Scanner scanner = new Scanner(is);
while (scanner.hasNext()) {
if (scanner.nextLine().contains(methodName)) {
System.out.print(methodName + " found in " + classFile.getName() + "\n");
found = true;
break;
}
}
}
}
public static void testMethod() {
System.out.println("testing");
}
static List<File> getFilesInDirectoryWithSuffix(File dir,String suffix) {
List<File> foundFiles = new ArrayList<>();
if (!dir.isDirectory()) {
return foundFiles;
}
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
foundFiles.addAll(getFilesInDirectoryWithSuffix(file,suffix));
} else {
String name = file.getName();
if (name.endsWith(suffix)) {
foundFiles.add(file);
}
}
}
return foundFiles;
}
}
