How to find static method calls in large Java project? - java

I'm refactoring some Java code to be more decoupled by changing some static method calls to non-static calls, for example:
// Before:
DAO.doSomething(dataSource, arg1, ..., argN)
// After:
dao.doSomething(arg1, ..., argN)
My problem is that in a large project, it can be hard to find where static method calls are being made. Is there an easy way to do this, either from the command line or in Eclipse?
Such a tool would need to let me ignore "benign" static method calls such as these (either by not finding them in the first place, or by allowing them to be easily deleted from the search results):
String.valueOf(...)
Integer.parseInt(...)
MyClass.someBenignStaticMethod(...)
Some clarifications:
I'm not interested in finding method calls made via reflection
I don't know what static methods currently exist in this project, so it's not as simple as searching for their callers using Eclipse's "Open Call Hierarchy" command (Ctrl-Alt-H), although an easy way to search for non-private static methods would let me use this approach
I'm also interested in finding calls to static methods located outside my project, e.g. javax.mail.Transport#send
I'm looking for a free (as in beer) solution

Do you really need to search? Why not comment out the static method calls one by one? When you compile it then it will flush out the references.

I'd use grep (-R on Linux) to search for initial caps-dot-camel case-open (I don't use it enough to give you the full command line). And then grep -v to get rid of some of the rubbish.
Well, really what I'd do is refactor incrementally. Changes a method, and see what breaks (if nothing breaks, delete the code).
Theoretically you could search through the class files looking for invokestatic. The FindBugs infrastructure would probably help out here (there may be better starting points).

Some IDEs provide support for refactoring. You can refactor every static method one-by-one.
In Eclipse, you can view the call hierarchy to see all the callers of such method. To view the call hierarchy you can select the method name and press Command-Alt-H, or Right-Click on symbol and choose 'Open Call Hierarchy).

We have a product called nWire for Java which might just help. nWire analyzes your code and builds a database of your code components and associations. You can see a brief demo on our web site.
We plan to have reporting capabilities added in the future. In the mean while, if you have some basic experience with databases, you can tap into the nWire repository and, with a simple SQL query, get a list of all your static methods (you can also see the invocations there). nWire uses the H2 database engine which is open-source and free.
I can assist in accessing the database. Drop me a line to support [at] nwiresoftware.com.

I've written a small Java program that uses the excellent ASM library. It lets you exclude packages like java.lang, and produces output that looks like this:
+ java
+ io
- File
# createTempFile(java.lang.String, java.lang.String)
+ javax
+ imageio
- ImageIO
# read(java.io.InputStream)
# write(java.awt.image.RenderedImage, java.lang.String, java.io.File)
+ mail
- Transport
# send(javax.mail.Message)
+ internet
- InternetAddress
# parse(java.lang.String, boolean)
+ xml
+ parsers
- DocumentBuilderFactory
# newInstance()
I'd prefer something that's more easily built into my existing build process, which uses CheckStyle, but this is the best solution I've come up with so far.

A possible solution could be a custom CheckSyle or PMD or ... warning. Currently I have the same challenge and trying it with CheckStyle. It seems to be right easy to write such an extention.

Related

How to fix IntelliJ IDEA method parameter auto-completion?

I am using IntelliJ IDEA 15, and I noticed that (by default) Eclipse offers a much more convenient auto-completion, when it comes to writing method calls, which require multiple parameters.
Eclipse automatically fills in default parameters and allows you to quickly navigate through them by pressing Tab:
However, IntelliJ IDEA does not handle it as conveniently and makes you write them manually:
Is there a way to make IntelliJ IDEA, handle method call auto-completion in a similar way to Eclipse's, and pre-write all the parameters for you, having you just press Tab (or another key) to navigate through them? If it is not possible in original IntelliJ, is there an add-on/plugin/external tool that will improve the intelligent code completion in such cases?
Note: I am not being lazy, it just gets quite annoying, having to manually complete each parameter and put a comma after each one, when code completion should do it for you.
IntelliJ doesn't do it and AFAIK there isn't a plugin for it.
There is no solution for you (unless you built a plugin yourself, but then you'd just have another job to maintain that plugin)
The alternative is to break the habit/need for it and use IntelliJ's Code Completion shortcuts:
Ctrl+P to view possible parameters for function.
Ctrl+Shift+Space to list the possible variables that could be entered as a parameter in the respective parameter position (based on type).
This also enters a comma if another parameter is required for the function.
Hardcoding numbers/strings as parameters to a custom function wouldn't be advisable as that negates the point of the parameters. It's better practice and more common to pass in a pre-defined variable; At which point Ctrl+Shift+Space is the easiest way for Code Completion.
This would also prevent you from closing quotations and adding commas.
Also note: IntelliSense is Microsoft's Intelligent Code Completion implementation which neither IntelliJ nor Eclipse uses.
As frant.hartm states in their answer:
Unfortunately the view of Intellij developers is that this feature would be too error prone. See this issue on youtrack.
They even state that people are welcome to make a plugin that does this.
The closest thing to this AFAIK is "method parameter completion", which allows you to auto complete parameters of current method as parameters of the inner method call at once (works for methods and constructors when calling super()).
Unfortunately the view of Intellij developers is that this feature would be too error prone. See this issue on youtrack.
IDEA doesn't fill the arguments automatically. You can use Ctrl+Shift+Space for auto-completion (completion is based on type, not name) or Ctrl+Alt+Space for suggestion. Or Ctrl+P to see what arguments are accepted.
Try
Ctrl + Space
for
Basic Code Completion
And like previously was written
Ctrl + Shift + Space
for
Type Code Completion
or try the second variant TWICE. More about Auto-Completing Code is in here

Finding called methods - reverse call hierarchy

Are there any tools that will, for a given method or class, list all methods that can be called by that method/class?
I am aware of code coverage tools, but I'm looking more for static analysis.
Obviously some kind of filtering system would be needed to stop the generated report being too big. I would want to identify all methods in the com.mycompany.* package hierarchy, for example.
I'm basically looking for an inverse version of the call hierarchy provided by IDEs like Eclipse and Idea.
bcel and asm permit to read and analyze class files. Then you can write the code which:
look in the target method all call ('invoke')
look into constant pool components for their resolution
I don't have anything more friendly...
You can try jarchitect tool, a static analysis tool that can help you to list all methods called by another method or a class.
In Eclipse, you can view the references to a method, class, or variable.
You can do this by right-clicking on the name of the object you're interested in, and selecting whichever scope applies to you:
References -> Workspace (Ctrl + Shift + G)
Project
Hierarchy
Working Set...
or by typing: Ctrl + Shift + G to find references in your Workspace by default.

Is it possible to prevent a class from using a method in java?

Suppose I have a class called Foo. This class will be modified by many people, and WILL print information to the console. To this effect, we have the following method:
private void print(String message){ ... }
which prints out to the screen in the format we want.
However, while reviewing code from other devs I see that they constantly call System.out.println(...)
instead, which results in barely-readable printouts.
My question is the following: is it possible to prevent any and every use of System.out.println() in Foo.java? If so, how?
I've tried looking this up, but all I found had to do with inheritance, which is not related to my question.
Thanks a lot!
N.S.
EDIT: I know that whatever I have to do to prevent the use of a method could be removed by a dev, but we have as a policy never to remove code marked //IMPORTANT so it could still be used as a deterrent.
EDIT2: I know I can simply tell the devs not to do it or use code reviews to filter the "errors" out but 1) I'm already doing it and it costs a lot of time and 2) the question is whether this is possible or not, NOT how to deal with my devs.
public methods are just that - public. There is no way to restrict access to them.
This kind of problem is usually "solved" by setting up some code-checker like PMD or checkstyle and integrating them into the continuous integration build. So violations of these stuff will be emailed to someone with a big hammer :-)
Although communicating that developers should not use System.out directly would be preferred, you could set System.out to another PrintStream, then use the alternative PrintStream in the private method. That way, when people use System.out.println they won't output anything but you'll still be able to use the alternative PrintStream... something like they do here: http://halyph.blogspot.com/2011/07/how-to-disable-systemout.html
Pre-commit hooks for your revision control system (SVN, Git, Mercurial) can grep for uses of System.{err,out} and prevent commit if they occur.
http://stuporglue.org/svn-pre-commit-hook-which-can-syntax-check-all-files/ is an example that takes an action for different changed files based on file extension for SVN. You should be able to modify that example to take an example based on some subset of Java files and reject if something like the following is true
egrep -q '\bSystem\.(err|out)\b'
You can redirect System.out calls to a streams that ignores the output or that redirects it to your logging system.
System.setOut(printStream);
You can also kill those using System.out.println in a production environment.
You can replace the OutputStream of System with your own implementation that would either throw an exception, or redirect the call to your own print implementation (which you would need to make public).
No, it's not possible to 100% prevent a class from ever using a specific method in Java.
Having that said...
My suggestion would be to add code analysis to your build process and failing the build on any occurrence of System.out.println. A good place to start if you're interested in going this route would be to check out PMD.
Also... have some constructive discussions with your developers and talk about why they're doing what they're doing. Good luck.

Can Java self-modify via user input?

I'm interested in an executed script allowing user input to modify the process and corresponding source.
What precedents exist to implement such a structure?
Yes, depending on what is meant.
Consider such projects as ObjectWeb ASM (see the the ASM 2.0 tutorial for a general rundown).
Trying to emit the-would-need-to-be-decompiled Java source code is another story: if this was the goal then perhaps the source should be edited, re-compiled, and somehow loaded in/over. (This is possible as well, consider tools like JRebel.)
Happy coding.
You should not be able to modify existing classes. But if you implement a ClassLoader then you can dynamically load classes from non-traditional sources: network, XML file, user input, random number generator, etc.
There are probably other, better ways.
Maybe the Java scripting API is what you're looking for:
http://docs.oracle.com/javase/6/docs/api/javax/script/package-summary.html
http://docs.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html
I wrote an app once that used reflection to allow tests to be driven by a text file. For instance, if you had a class like this:
class Tuner(String Channel) {
tune(){...
play(){...
stop(){...
}
You could execute methods via code like:
tuner=Channel 1
tune tuner
play tuner
stop tuner
It had some more capabilities (You could pass objects into other objects, etc), but mostly I used it to drive tests on a cable box where a full write/build/deploy in order to test took on the order of a half hour.
You could create a few reusable classes and tie them together with this test language to make some very complex and easy to create tests.
THAT is a DSL, not monkeying around with your loose-syntax language by eliminating parenthesis and adding underscores and dots in random locations to make it look like some strange semi-English.

Do I have any method to override System Properties in Java?

I am getting a practical issue and the issue can be dascribed as follows.
We are developing a component (Say a plugin) to do some task when an event is triggered within an external CMS using the API provided by them. They have provided some jar libraries, So what we are doing is implementing an Interface provided by them. Then an internal method is called when an event is triggered. (The CMS is creating only one instance of class when the first event triggers, then it just executes the method with each event trigger)
The function can be summarized as follows,
import com.external.ProvidedInterface;
public class MonitorProgram implements ProvidedInterface{
public void process(){
//This method is called when an event is triggered in CMS
}
}
Within our class we are using "javax.net.ssl.HttpsURLConnection" (JAVA 1.5). But HttpsURLConnection migrated to javax.net.ssl from com.sun.net.ssl for 1.4. But it seems the CMS I am referring to (We dont know their implementation actually) uses something like this
System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");
leading to a ClassCastException in our code.
I think my question is clear. In our case we cant set VM parameters,
-Djava.protocol.handler.pkgs=
Also we cant set it back using,
System.setProperty("")
because the VM instance is same for CMS and our program.
What can I do for get this problem resolved? And idea or experiences?
This is not clear for me.
Do you want to overwrite a system property?
You can do this.
Overwrite the System.property before calling the external library method and when the method returns you can set the old System.property back
final String propertyName = "Property";
String oldProperty = System.getProperty(propertyName);
System.setProperty(propertyName,"NEW_VALUE");
monitorProgram.process();
System.setProperty(propertyName,oldProperty);
Or do you want to prevent, that the called process overwrites the system.property?
And why you can not set the system property by hand?
I don't think you are going to have much success getting two pieces of code to use different properties.
In your own code however, you can define your own URLStreamHandlerFactory. Doing this will allow you to create a javax.net.ssl.HttpsURLConnection from a URL. While protocol handlers aren't the easiest thing to figure out, I think you can get them to do the job.
See http://java.sun.com/developer/onlineTraining/protocolhandlers/
Find the offending class in the stack trace
Use jad or a similar tool to decompile it.
Fix the name of the property
Compile the resulting file and either replace the .class file in the CMS's jar or put it into a place which is earlier in the classpath.
Use ant to automate this process (well, the compile and build of the JAR; not the decompiling)
When it works, make sure you save everything (original file, changed file, build file) somewhere so you can easily do it again.
While this may sound like a ridiculous or dangerous way to fix the issue, it will work. Especially since your CMS provider doesn't seem to develop his product actively.

Categories

Resources