How to build call graph using JDT - java

In eclipse, there is "Call Hierarchy" to find the call graph(or method invoke relationship) easily.
I want to find some APIs to extract this relationship. However I cannot find any existing tutorial to help me. Can anybody give me some clues? Mainly I want to know which class in JDT should be used and what should be the input.
By the way, the goal is to extract this invoke relationship, so some other way may also help. I tried SOOT, but I think JDT is better for it has both caller and callee.

I figured it out looking the JDT code for those features, it's a nice place to find about this things.
Basically you can start with the following code snippet:
CallHierarchy callHierarchy = CallHierarchy.getDefault();
IMember[] members = { method };
MethodWrapper[] callers = callHierarchy.getCallerRoots(members);
Where method is the IMethod type from JDT.
With the resulting MethodWrappers you can get all information about it.
It's important to notice that the class CallHierarchy is internal, so it can break in a Eclipse release, but I don't know a public API for that.

Related

Java: Making own annotation that highlights methods and adds custom messaging

I have some importand methods in code that are used in a wrong way, people don't get the whole context of the process and invokes wrong methods, for example setters. If I had something like #Deprecated it could highlight / strike/ underline methods and show som info when somebody uses it. For example someone set some variables that are even not persisted as he thought that it would persist. Another person changed one method and spoiled dozen of usecases becaouse he didnt know about them..
I use Java7 and IntelliJ Idea 14
Instead of using an annotation, program defensively, check if the parameters you get make sense. Write tests to verify what happens when invalid input is provided.
I think Automated Tests, Good Method Names and such will do more good than some fancy IDE plugin to stop other developers from invoking wrong methods.

Replacing a method in a compiled .class file

Interesting question here. So I have a .jar I received and it is obfuscated, meaning when I decompile the .class files it doesnt show up 100% perfect so I cannot recompile it. However the only method I need to change has been converted perfectly (but the class does not)). Is there a way to somehow change the .java code and inject replace the method within the class file without totally recompiling?
If this fails im going to bytecode.
Thanks!
EDIT: As a follow up question / or a hack around replacing the WHOLE method. I'm really just trying to change a variable that the method generates locally. If there are any better ways to do that.
Depending on what you really want to do, I do not recommand to decompile / modify / recompile the code (be it for legal, maintainance, understandability, testability reasons.)
Bytecode manipulation may not be the best solution either, but if you want to follow this way have a look at the ASM project, it's a widespread bytecode manipulation framework used by many known projects.
If I were you I would first give a try to aspects (AspectJ.) The power of aspects is that you don't touch existing code, but tell the VM what to do when / before / after / in place of calling a specific method. It allows you to point out the exact context and change, enhance the behavior of the code, by writing your own code in a decoupled fashion.
Hope it helps.
Sorry, this is not an answer, but it is too long for a comment...
I am reflecting this code, not using it as a library. So I dont really need to "use" this code (aka I'm just reflecting and calling functions at runtime).
I'd call the "reflecting and calling functions at runtime" as using the code.
There might be the reasons why to do that, but I'd prefer to simply call the function as a library function if possible (which should be possible if you can do the same using reflection).
...and manually overload it.
There is nothing simpler that extending the class and override a "wrong" method. As of my understanding even if you want to "inject" the method, you have to have the code somewhere. How you will test such code? It'd be a lot easier to just extend the class... Can you specify in bigger detail what you want to achieve with a reasoning why you cannot use what I wrote above?
If you want to change just one method you can actually extend the class and then #Override the method!
Don't know if this is the perfect way to do it,but it works!

How to convince Eclipse to offer non-requisite methods?

(Eclipse v4.2.2/JDT v3.8.2)
How can I convince Eclipse to offer eg, Serializable's readObject(...) and writeObject(...) when using content assist? These methods never appear in the list of method names, even when the surrounding class implements Serializable.
Additionally, if this is possible, how would I customize the skeleton to contain eg, in.defaultReadObject();?
I understand why they don't appear, but is there any way to make them do so?
What you are looking for is called a Code Template. These are helpful for all kinds of repetitive code tasks. You'll never have to type a for loop again.

Write An Annotation to Constrain Class/Method Naming in Java?

I'm trying to find a way to use annotation to constrain namings in Java. Might be something looks like this:
#Getter
public String getXxx();
And when the method name does not meet the convention, for example not started with "get", the compiler will throw some error. So that during the coding progress in IDE, such like eclipse, the developer will be able to notice.
I'm getting some ideas from this article, but it's too long and complex for me.
Any simpler examples or directions would be very nice.
Check out the custom annotations guide HERE
It also shows you how to use reflection to get info from the annotated elements, you could easily use this to fetch the method name and verify whether it meets your convention and take appropriate actions etc...
Didn't get to do it myself but it appears to be possible. You can do some background reading or go directly to the 3rd party tool they link.

Strategies for reverse engineering project that uses Guice?

I have tried to understand dependency injection and not quite gotten it, except I have managed to pick up the understanding that it makes it hard to understand somebody else's code. :'(
Anyway, I'm not sure how to briefly describe my problem but I will try. I am currently the sole coder working on a Java project that's been worked on by dozens of loners over about six years. It makes heavy use of Google's Guice library. I'm supposed to take some existing code and implement it differently; specifically, use the existing methods for password authentication and, instead of applying it to each JMenuItem in a JMenu, apply it to the whole JMenu, so that if the wrong password or no password is entered, all JMenuItems are disabled. This doesn't happen if the password is wrong, leading me to believe the problem is in the if statement, which is a long string of dependencies in itself:
if (!ViewScanApp.getApplication().getHistoryManager().isAuthenticated())
I trace my way back through this, to find that the HistoryManager class is an interface, and there my path seems to die; there's no code there, and it doesn't make a reference to any other class. I have found the end of the path through random exploration of the 100-odd classes in the project, but I can't quite seem to connect them. I cannot find where the first class I can find on the other end of this stack, AccessManagerImpl, gets called.
I could use an explanation of dependency injection that might be applicable to this situation. Thank you so much!
Assuming there's no #ImplementedBy annotation on the HistoryManager interface, you'll need to examine the Guice Module that is responsible for binding this type.
In Eclipse, there is a command to look for occurrences of a class. I'll bet that Netbeans has something similar. Use it to look for occurrences of HistoryManager. At least one of these should occur in a class that implements com.google.inject.Module (or extends AbstractModule). You'll likely see something like
protected void configure() {
…
bind(HistoryManager.class).to(HistoryManagerImpl.class);
…
}
Or, if you like quick-and-dirty empiricism, you can throw in a println():
HistoryManager mgr = ViewScanApp.getApplication().getHistoryManager();
System.out.println("HistoryManager implementation: " + mgr.getClass());
if (!mgr.isAuthenticated())
…
However you locate it, HistoryManagerImpl class is where you'll want to pick up the trail.
I haven't used it, but the Guice graphing tool might be helpful too.
Fire up a debugger. It will walk you through the exact class that is implementing that interface (assuming you have the source code to it)
Whenever you have an interface definition in Eclipse which is injected with Guice, instead of using F3 to go to the defintion which you would do if it was a class, then use Ctrl-T to choose among the implementations of that interface.
If you have more than one to choose from, then you need the module bindings printed out so you know which one to pick. Unfortunately Eclipse doesn't understand injection yet.

Categories