1

Suppose I have two packages(package1,package2) with one class in each package(package1.A, package2.B). I need to identify references from package1.A to package2.B and vice versa using a java program, and also references to any methods in each class as well.

The code would be something like this:

package package1;
public class A{
    public  A(){
        Class<?> clazz = Class.forName("package2.B");
        Method mthd = clazz.getMethod("someMethod", Integer.TYPE);
}
    public static void main(String[] args) {
        new A(); 
    }

Class B goes like this:

package package2;
    public class B {
        public B someMethod(int someParam) {
            return null;
        }
    }

I just need a few pointers on how I should get started in using parsers for this problem. What kind of rules must I keep in mind? The goal of my problem is to identify dependency.

rabbar
  • 109
  • 1
  • 1
  • 9
  • 2
    You'd pretty much need to write a full parser for Java. And you'd need to iterate through the parse tree of every file of source code, identifying the type of each expression to see if it matches the class you're looking for. – Dawood ibn Kareem Aug 13 '18 at 21:24
  • 1
    Please be very precise about the level of meta we're talking here. Do you have a program that is trying to find, in its _own_ code, references to a class? Are you trying to analyze another set of code? Or do you have one codebase and you're just trying to examine it, like in an IDE? – Louis Wasserman Aug 13 '18 at 21:26
  • You can either use the functionality of an IDE to help you find them, or you can `grep` the directory structure of your project using something like `grep -r --include \*.java ClassName ./` – chb Aug 13 '18 at 21:26
  • 1
    Oh, did I misinterpret the question? I thought you were asking about writing a Java program that does this. Do you just mean how to do it in your IDE? OK, that makes it a different question. Which IDE are you using? – Dawood ibn Kareem Aug 13 '18 at 22:09
  • @DawoodibnKareem Yes, I need to write a program that does this. – rabbar Aug 13 '18 at 22:56
  • 1
    Oh, OK, that's far too broad to answer on a single page in Stack Overflow. But do some research into parsers - that will get you started. – Dawood ibn Kareem Aug 13 '18 at 23:00
  • 1
    Detecting this is hard enough, but detecting such things in reflection code is probably impossible. I would not want to try to detect something like this: `String name = String.format("%c%s%c%s", 32, "java.lang", 46, "System"); Class.forName(name.substring(1));` – VGR Aug 13 '18 at 23:16
  • Question for OP: Why do you "need" to do this? This sort of question is common among beginners, and there is almost certainly a better way to achieve what you want. Try explaining why you need to do that, and then we may be able to provide much better guidance. – sorifiend Aug 14 '18 at 03:57
  • @sorifiend This is just a simple example of what I really need to do. I'm trying to find dependencies between the two classes and their various methods. – rabbar Aug 15 '18 at 00:29
  • If I had to do this myself, I would probably write a Java agent that will be invoked by a JVM as it loads the bytecode for the classes to be analyzed into a JVM. The Java agent API calls callbacks that your agent provides, telling you about each class, method, and function call that it sees in the code - and you can then save and use that data however you need to... – moilejter Aug 15 '18 at 01:35
  • I've thought about this problem too. It would be nice to be able to generate some kind of dependency graph of, e.g., all methods in a class/package. However, it turns out to be not so simple. One way to try to solve the task is to use [Java's compiler API](https://www.javacodegeeks.com/2015/09/java-compiler-api.html). This will allow you to syntactically analyse any Java source code. Unfortunately, this does not get us very far because we'd have to re-implement the resolution of classes and methods which the JVM automatically does at runtime. – JimmyB Aug 17 '18 at 00:14

1 Answers1

0

I was not going to post this because it's not great, but since it has been a couple days and you have not had a lot of response, here is a different sort of answer based on your comment:

I'm trying to find dependencies between the two classes and their various methods.

If you only need to find dependencies and calls within your own application (Not external libraries) then read on.

Consider injecting a line or two of code into every method (Easily done by a script at compile time?), and have this information logged. For example, you can use variations of object.getClass().??? to find info about the current method including its package, class, and method name.

For example this one just outputs info directly to console:

StackTraceElement[] ste = Thread.currentThread().getStackTrace();
System.out.println("Called by: "+ste[ste.length - 2].getMethodName());
Object object = new Object(){};
System.out.println("Method details: "+ object.getClass().getPackage().getName() +" - "+ object.getClass().getName() +" - "+ object.getClass().getEnclosingMethod().getName());

For every method that these lines are inserted into it will spit out something like this on the console every time it is called:

Called by: source
Method details: myPackage - myClass$1 - myMethod

Some real results from a quick test on one of my applications by throwing the above into several classes:

Called by: getStackTrace
Method details: testdump - testdump.TestDump$1 - main
Called by: pumpEvents
Method details: testdump - testdump.Rect$1 - paintComponent
Called by: checkFileSize
Method details: update - update.FTP$2 - checkFileSize
Called by: checkFileSize
Method details: update - update.FTP$1 - download
Called by: pumpEvents
Method details: testdump - testdump.Rect$1 - paintComponent
...

We can very easily see exactly the two different packages that were called, and we can generally see where it was called from, although you will need to play around with ste[ste.length - 2].getMethodName() to return different lines depending on how far back on the stack trace that you want to see. Obviously, this should be used in debug mode only, and it will generate a lot of junk, but depending on the size of your application it should be a simple matter of inspecting the output results, either manually or by making a short program that builds a tree of dependencies for you to inspect.


Alternatively, you may be able to use the Java 9 stack walking API in a similar way: https://stackoverflow.com/a/45812871/1270000

sorifiend
  • 5,927
  • 1
  • 28
  • 45
  • Yell out if you wanted info about classes outside of your application instead, and I am happy to delete this answer so that you will get more visibility. – sorifiend Aug 17 '18 at 00:23