Consider the following code:
public String foo(){
String bar = doStuff();
return bar;
}
And then later:
public void test(){
doSomeLogicHere();
String result = foo();
}
Note that in test I get a String named result at the end of the function. Eclipse knows this is an unused variable, as it warns about it. What I'm wondering is, do these Strings get compiled out as if the call was just foo() without saving the returned String? If I commented out String result = when I'm not using it would I reduce memory consumption or does it not matter since the String is still generated and returned in foo()?
I have some debugging logic in an application I'm writing like this, and I'm wondering if it's worth it to comment out all of the Strings for a release/when I'm not using them.
As far as I'm aware, compiler doesn't automatically remove unused variables. That's usually the job for optimizers/obfuscators.
For instance, in Android ProGuard removes all unused variables when you build your android app in release mode.
The result assignment won't make any difference performance wise: the Java JIT in the JVM will optimise away these unused variables in nearly all cases.
I personally fix these kind of things just to keep my code clean and warning-free.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have some code which is like:
String country = null;
country = getEuropeanCountry(); //Germany
//after few lines of code
country = getAsianCountry(); //Japan
//after few more lines
country = getNorthAmericanCountry(); //Canada
/*and the code follows by assigning a different country value to the same variable "country"*/
I have this kind of usage in most of my code.
For some reason, my application throws "Error java.lang.OutOfMemoryError: GC overhead limit exceeded".
So I tried with VM argument: -XX:-UseGCOverheadLimit
Then my app ran successfully but I noticed that it is consuming more memory (I had to set -Xmx to 5g or 6g; otherwise I get: out of memory error).
I checked my app and there are no memory leaks. But most of my code has the similar code that I posted above.
Can anyone tell me if it is beneficial for memory management if I refactor the above code to:
String europeanCountry = getEuropeanCountry(); //Germany
//after few lines of code
String asianCountry = getAsianCountry(); //Japan
//after few more lines
String northAmericanCountry = getNorthAmericanCountry(); //Canada
/*and the code follows by assigning a different country value to a different String variable*/
I can't use collections. I mean, in general, which way is better to use heap space and garbage collector efficiently?
For the question " I mean, in general, which way is better to use heap space and garbage collector efficiently?"
Lets look at the String implementation e.g. jdk8 https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/String.java
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
So it is a final character array - it cannot be reasigned or changed. So it is generated on the heap in your method and is never changed - only a reference(a name) is generated.
To make no mistake lets also look at the constructor of a String (doing smth. like eg. "newString = new String(otherString)":
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
Also in that case no additional space on the heap is allocated - it stays the same single final char array on the heap.
So you can assign a new String to a reference.(Give it an additional name). But it is allways the same unique String generated in your method and no new space on the heap is allocated.
So comparing the two methods in a first narrowing:
String europeanCountry = getEuropeanCountry();
String asianCountry = getAsianCountry();
and
String country = null;
country = getEuropeanCountry();
country = getAsianCountry();
Both will formaly create the same amount of Strings on the heap as the String is allways generated in the same methods. The variable are only references to that.
The only difference is that reusing in the second case allows formaly the String to be earlier garbage collected(In the moment the reference to it is removed by reusing the variable).
So with the second approach(reusing) you may generate a smaller memory footprint for a neclectable time.
I said in a first narrowing as this is only true if there is no other reference to the String and without optimization - so if no other reference exists and no optimization would take place the above would be the case.
However in your above code the variables don't exit scope and are never used. The compiler will detect this and no variable will be assigned at all. Depending on what the methods do they may be inlined and also not called. So what the methods you call look like makes a difference. Depending how complex they are the space on the heap is allocated or not.
Also the other way round: if you use the variable and runtime detects that you will likely call the method again for the same value, the value will be kept on the heap and not freed even if there is formal no reference and it could formally be garbage collected - so the assigment again makes no difference but the call of the method.
Also the obvioue: if the methods don't only generate the Strings but pull them from somewhere(a container) or store them somewhere that other reference is the one for which space on the heap is kept (and is) allocated and your assignment makes no difference at all regarding heap: it is the same final char array on the heap.
With that in mind the problem you are facing is most probably not that assignment of Strings but the design of your code. It must be a by far more complex scenario in which references are kept longer.
So far for your question.
For your problem i would look out:
for containers
where variables are generated
for frequent use . That is calling the methods very frequently for a lot of different values as in such case they are kept in memory for the next assumed call to happen.
for code where it is not easy to follow the flow of the data. The compiler optimizes by analyzing the flow. If you can't follow, it is more likely that the compiler can't neither than in other parts.
Assuming lines of code shown are from single method(let me know if that's not the case), there are at least 3 issues I can point outwith the code:
it seems method size is too large. Prefer writing methods that are as concise as possible and do just "one thing" and do it well.
too much state change. In the 1st example where you set variable 'country' to 3 different method return values.
consider using polymorphism, rather than repeating code in an if-else fashion for fetching the country
finally, it's not clear how country values are used in methods.
I've got a recursive method which has local String variables:
private void recursiveUpdate(int id){
String selectQuery="Select ...";
String updateQuery="Update or rollback ..."
...
for(int childID: children)
recursiveUpdate(childID);
}
Is there any reason to externalize local String variables like this:
private static final String selectQuery="Select ...";
private static final String updateQuery="Update or rollback ..."
private void recursiveUpdate(int id){
...
for(int childID: children)
recursiveUpdate(childID);
}
From a technical point of view the difference between the two should be negligible since in either case you'd always use the same string instances. If you are parsing those query in every call you might consider externalizing that as well (e.g. using prepared statements).
From a development point of view, I'd probably externalize the queries to separate them from the call logic.
In the former case, you are relying on the compiler to recognize that those strings are unchanging across all calls so it doesn't need to give a fresh copy of each variable to each invocation of recursiveUpdate, whereas in the latter case, there is no question about it.
Yes. You'd want to externalize the variables. If left as a local variable, amd depending on the size of the call stack, you could quickly accumulate many string objects and lower efficiency. Even worse if making edits to the string inside the recursive method. Also, you will not be making changes to the strings as it appears to me, so if used as a 'reference' it would be better to externalize it.
Typically you should be concerned with the size of your stack memory when making recursive calls. This tells the cpu where to jump when the method completes. It contains your method parameters and returning location.
Object instantiated within the body of the method are saved in the heap. In this case, I think the compiler will figure out that these are constants and save them to static memory. The heap is much larger and is more likely to survive the recursion when objects are instantiated so I wouldn't worry about it.. By moving object out, you'll save a little space in your heap.
IMO, it's best to move the variable out, if the values are always the same (no-dynamic). This way, if they ever change, you can find them easily.
I am developing a dynamic web project using Tomcat. It is useful to have a global flag that is the only thing I have to change between my development and deployment servers. The biggest use of the flag is with print statements.
public class Debug {
public final static boolean DEVEL = true;
public static void print(String message){
if(DEVEL){
System.out.println(message);
}
}
}
My question is, will java compile out the print statements. i.e. if the devel tag is false, the messages will obviously not print but will they be included in the class files (devel is final). This is a question of efficiency. I've heard that the java compiler is very smart but will it pick up on this.
use the 'final' attribute (as you did), and it will compile out the code:
public static final boolean DEVEL = false;
You can check by grepping the resultant class file for a string that would appear only if the code were compiled.
Take a look into this article:
http://www.javaworld.com/javaworld/jw-03-2000/jw-03-javaperf_4.html
The code you presented is called a "dead code" so it will not be included in the compiled class file if you set DEVEL to false it will not be included in the bytecode.
Also, check the command
javap -c
to see the resulting bytecode of your class.
If you want to have the compiler not compile it out, use this:
public final static boolean DEVEL = Math.random() > -1;
The compiler won't know that this is always true. (of course use < -1 for false)
I find this trick handy when you want to remove code temporarily without having the compiler complain abut dead code, eg:
void myMethod() {
// temporarily exit early
if (Math.random() > -1) return;
// usual code
}
I have never seen the compiler remove code like this, however the JIT will effectively remove code which never runs. Assertions is a common use case for this. There may still be a notional cost but generally one not worth worrying about. i.e. less than 1 nano-second.
The cost can be greater if the toString() method of the message is costly. The toString method of a large sql query in a prepared statement caused a heap overflow due to this line. Thus the standard did not remove it.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
OK, after reviewing some code with PMD and FindBugs code analyzers, i was able to do great changes on the reviewed code. However, there are some things i don't know how to fix. I'll iterate them bellow, and (for better reference) i will give each question a number. Feel free to answer to any/all of them. Thanks for your patience.
1. Even tough i have removed some of the rules, the associated warnings are still there, after re-evaluate the code. Any idea why?
2. Please look at the declarations :
private Combo comboAdress;
private ProgressBar pBar;
and the references to objects by getters and setters :
private final Combo getComboAdress() {
return this.comboAdress;
}
private final void setComboAdress(final Combo comboAdress) {
this.comboAdress = comboAdress;
}
private final ProgressBar getpBar() {
return this.pBar;
}
private final void setpBar(final ProgressBar pBar) {
this.pBar = pBar;
}
Now, i wonder why the first declaration don't give me any warning on PMD, while the second gives me the following warning :
Found non-transient, non-static member. Please mark as transient or provide accessors.
More details on that warning here.
3. Here is another warning, also given by PMD :
A method should have only one exit point, and that should be the last statement in the method
More details on that warning here.
Now, i agree with that, but what if i write something like this :
public void actionPerformedOnModifyComboLocations() {
if (getMainTree().isFocusControl()) {
return;
}
....//do stuffs, based on the initial test
}
I tend to agree with the rule, but if performance of the code suggest multiple exit points, what should i do?
4. PMD gives me this :
Found 'DD'-anomaly for variable 'start_page' (lines '319'-'322').
when i declare something like :
String start_page = null;
I get rid of this info (level of warning is info) if i remove the assignment to null, but..i got an error from IDE, saying that the variable could be uninitialized, at some point later in the code. So, i am kind of stuck with that. Supressing the warning is the best you can do?
5. PMD Warning :
Assigning an Object to null is a code smell. Consider refactoring.
This is the case of a singletone use of GUI components or the case of a method who returns complex objects. Assigning the result to null in the catch() section it's justified by the need to avoid the return of an incomplete/inconsistent object. Yes, NullObject should be used, but there are cases where i don't want to do that. Should i supress that warning then?
6. FindBugs warning #1:
Write to static field MyClass.instance from instance method MyClass.handleEvent(Event)
in the method
#Override
public void handleEvent(Event e) {
switch (e.type) {
case SWT.Dispose: {
if (e.widget == getComposite()) {
MyClass.instance = null;
}
break;
}
}
}
of the static variable
private static MyClass instance = null;
The variable allows me to test whether the form is already created and visible or not, and i need to force the re-creation of the form, in some cases. I see no other alternative here. Any insights? (MyClass implements Listener, hence the overrided handleEvent() method).
7. FindBugs warning #2:
Class MyClass2 has a circular dependency with other classes
This warning is displayed based on simple imports of other classes. Do i need to refactor those imports to make this warning go away? Or the problem relies in MyClass2?
OK, enough said for now..expect an update, based on more findings and/or your answers. Thanks.
Here are my answers to some of your questions:
Question number 2:
I think you're not capitalizing the properties properly. The methods should be called getPBar and setPBar.
String pBar;
void setPBar(String str) {...}
String getPBar() { return pBar};
The JavaBeans specification states that:
For readable properties there will be a getter method to read the property value. For writable properties there will be a setter method to allow the property value to be updated. [...] Constructs a PropertyDescriptor for a property that follows the standard Java convention by having getFoo and setFoo accessor methods. Thus if the argument name is "fred", it will assume that the reader method is "getFred" and the writer method is "setFred". Note that the property name should start with a lower case character, which will be capitalized in the method names.
Question number 3:
I agree with the suggestion of the software you're using. For readability, only one exit point is better. For efficiency, using 'return;' might be better. My guess is that the compiler is smart enough to always pick the efficient alternative and I'll bet that the bytecode would be the same in both cases.
FURTHER EMPIRICAL INFORMATION
I did some tests and found out that the java compiler I'm using (javac 1.5.0_19 on Mac OS X 10.4) is not applying the optimization I expected.
I used the following class to test:
public abstract class Test{
public int singleReturn(){
int ret = 0;
if (cond1())
ret = 1;
else if (cond2())
ret = 2;
else if (cond3())
ret = 3;
return ret;
}
public int multReturn(){
if (cond1()) return 1;
else if (cond2()) return 2;
else if (cond3()) return 3;
else return 0;
}
protected abstract boolean cond1();
protected abstract boolean cond2();
protected abstract boolean cond3();
}
Then, I analyzed the bytecode and found that for multReturn() there are several 'ireturn' statements, while there is only one for singleReturn(). Moreover, the bytecode of singleReturn() also includes several goto to the return statement.
I tested both methods with very simple implementations of cond1, cond2 and cond3. I made sure that the three conditions where equally provable. I found out a consistent difference in time of 3% to 6%, in favor of multReturn(). In this case, since the operations are very simple, the impact of the multiple return is quite noticeable.
Then I tested both methods using a more complicated implementation of cond1, cond2 and cond3, in order to make the impact of the different return less evident. I was shocked by the result! Now multReturn() is consistently slower than singleReturn() (between 2% and 3%). I don't know what is causing this difference because the rest of the code should be equal.
I think these unexpected results are caused by the JIT compiler of the JVM.
Anyway, I stand by my initial intuition: the compiler (or the JIT) can optimize these kind of things and this frees the developer to focus on writing code that is easily readable and maintainable.
Question number 6:
You could call a class method from your instance method and leave that static method alter the class variable.
Then, your code look similar to the following:
public static void clearInstance() {
instance = null;
}
#Override
public void handleEvent(Event e) {
switch (e.type) {
case SWT.Dispose: {
if (e.widget == getComposite()) {
MyClass.clearInstance();
}
break;
}
}
}
This would cause the warning you described in 5, but there has to be some compromise, and in this case it's just a smell, not an error.
Question number 7:
This is simply a smell of a possible problem. It's not necessarily bad or wrong, and you cannot be sure just by using this tool.
If you've got a real problem, like dependencies between constructors, testing should show it.
A different, but related, problem are circular dependencies between jars: while classes with circular dependencies can be compiled, circular dependencies between jars cannot be handled in the JVM because of the way class loaders work.
I have no idea. It seems likely that whatever you did do, it was not what you were attempting to do!
Perhaps the declarations appear in a Serializable class but that the type (e.g. ComboProgress are not themselves serializable). If this is UI code, then that seems very likely. I would merely comment the class to indicate that it should not be serialized.
This is a valid warning. You can refactor your code thus:
public void actionPerformedOnModifyComboLocations() {
if (!getMainTree().isFocusControl()) {
....//do stuffs, based on the initial test
}
}
This is why I can't stand static analysis tools. A null assignment obviously leaves you open to NullPointerExceptions later. However, there are plenty of places where this is simply unavoidable (e.g. using try catch finally to do resource cleanup using a Closeable)
This also seems like a valid warning and your use of static access would probably be considered a code smell by most developers. Consider refactoring via using dependency-injection to inject the resource-tracker into the classes where you use the static at the moment.
If your class has unused imports then these should be removed. This might make the warnings disappear. On the other hand, if the imports are required, you may have a genuine circular dependency, which is something like this:
class A {
private B b;
}
class B {
private A a;
}
This is usually a confusing state of affairs and leaves you open to an initialization problem. For example, you may accidentally add some code in the initialization of A that requires its B instance to be initialized. If you add similar code into B, then the circular dependency would mean that your code was actually broken (i.e. you couldn't construct either an A or a B.
Again an illustration of why I really don't like static analysis tools - they usually just provide you with a bunch of false positives. The circular-dependent code may work perfectly well and be extremely well-documented.
For point 3, probably the majority of developers these days would say the single-return rule is simply flat wrong, and on average leads to worse code. Others see that it a written-down rule, with historical credentials, some code that breaks it is hard to read, and so not following it is simply wrong.
You seem to agree with the first camp, but lack the confidence to tell the tool to turn off that rule.
The thing to remember is it is an easy rule to code in any checking tool, and some people do want it. So it is pretty much always implemented by them.
Whereas few (if any) enforce the more subjective 'guard; body; return calculation;' pattern that generally produces the easiest-to-read and simplest code.
So if you are looking at producing good code, rather than simply avoiding the worst code, that is one rule you probably do want to turn off.
Say way have a variable (let's say String Str) and the value of Str starts of as " " then as some code is running it is set to "test" then somewhere else in the code it is changed again to say "tester". Now in the program I want to find out what the previous value of Str was. Is this possible in Java?
So I am saying that the variable gets changed twice, and you want to find out what Str was before it got changed for the second time. So in the example above the latest value of Str would be "tester" but I wanted to find out what Str was before this (assuming you had no idea what it was before it was changed to tester) in this case I would want to be able to find out that Str was "test".
Is it at all possible to do this in Java?
No, it's not possible, you have to save the previous value before you change it to do what you're asking for.
Not as a native part of the language, no. You could write a setter that saved the current (previous?) value when the String changes, though.
private String str;
private String prev;
setStr(String s)
{
prev = str;
str = s;
}
Then just write a separate getter for prev.
Of course, this solution relies on you always using the setter to change the value of str.
Also, as deworde points out, if your program doesn't need this information, then you shouldn't modify your program to save it. If you need the information for debugging purposes you can just set a watch in your IDE's debugger.
Simple answer, no.
However, you could use:
AOP
An AOP framwork, such as AspectJ could intercept assignments to a variable.
See AspectJ pointcut reference
JavaBeans Property Change Support
You could use standard JavaBean setters, getters to encapsulate your field. Then you can register listeners on a bean to listen out for property changes, and even veto that change.
See JavaBean Spec for more information.
Example listener:
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
public class MyBeanListener implements PropertyChangeListener,
VetoableChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.printf("Notifed of property changed event: %s => %s%n", evt
.getOldValue(), evt.getNewValue());
}
#Override
public void vetoableChange(PropertyChangeEvent evt)
throws PropertyVetoException {
System.out.printf("Notified of vetoable change event: %s => %s%n", evt
.getOldValue(), evt.getNewValue());
}
}
If you really have a strong need for this you could use the following code:
public class Main
{
public static void main(final String[] argv)
{
SavedValue<Integer> i;
i = new SavedValue<Integer>();
i.set(7);
System.out.println(i.get());
System.out.println(i.getOld());
}
}
class SavedValue<T>
{
private T oldValue;
private T value;
void set(final T val)
{
oldValue = value;
value = val;
}
T get()
{
return (value);
}
T getOld()
{
return (oldValue);
}
}
Perhaps you could explain why you want the old value? I am sure we can give you much better answers if we knew why yoiu wanted it.
You already got the two simple answers:
No, Java itself doesn't allow that
You can use setters and implement a mechanism to keep the old value(s)
But there is a third one which I haven't seen so far:
It should be possible to write an Aspect in AspectJ that triggers on the assignment. So it would have a similar effect as a setter, without the actual setter. If you are working with code that you don't want to or cannot change this might be an option.
Note that while AspectJ isn't Java the result is normal byte code, so it should be compatible with most environments.
Of course instead of using AspectJ you could do this with CGLIB.
It looks like you're using this for debugging, am I right?
Visual Studio, or any decent debugger should allow you to print a trace of the value every time it's set just by putting a "tracepoint" before and after all the calls that set the value.
You just alter the properties of a normal breakpoint to print a statement rather than halt execution.
In VS2005 this is done by:
Bringing up the breakpoint window
Right-clicking on the breakpoint
Selecting the option "When Hit...".
Selecting "Print a Message" and entering a message
Making sure that "Continue Execution" is still selected.
This normally slows the program down significantly while debugging, so it's of little use for time-dependent debugging; but it's still allowed me to follow a variable's states (ABCDFEGH...)
Of course, if you do want to halt execution, just dump a normal breakpoint in.
You may try to use a stack data structure. It will keep all previous values in the right order. You may implement your own or use the java Collections one:
Deque<Integer> stack = new ArrayDeque<Integer>();
Each time you set the variable, put it in the stack (either through setter or AOP as mentioned in the other answers).
That way, you will be able to access al previous values.
Indeed, this is not possible. You'd have to create your own String class that had some sort of memory to achieve this.
In addition to what Stefan said, I would recommend a List structure of some kind containing all the historical values.
When you want to change the value, just add a new value to the end of the list. When you want to get the current value, just look at the last value. If you want to see previous values, start from the end of the list.
If you could find the previous state of the program, there would never be any garbage to collect and the program would very quickly run out of memory.
For specific variables, you could use, say, a LIFO stack. Instead of an assignment you would push to the stack. Instead of reading the variable, you would peek. The contents of the stack can be examined to find historical values.
Another approach would be to use instrumentation. This allows you to, with sufficient skill and patience, rewrite byte code to do what ever you want.
Perhaps you want to stand back a bit and look at what you are actually trying to achieve.
I don't know the reasons for wanting to do this, but I'm guessing it's debugging of some kind.
If you're using eclipse, you can set breakpoints that trigger when a variable changes. That might achieve what I assume you're trying to get to.
This is in fact possible using something called a Historical Debugger, and it is accomplished by instrumenting the bytecode so that any assignment to the variable is recorded.
Gooogle Bil Lewis Historical Debugger for one example. Note that most of this software is in what you'd call an 'initial beta' phase.
Have you heard about Jive? It allows backward stepping in debug so this is partially answer to your question Read here: http://www.cse.buffalo.edu/jive/
Yes!! When you change the value, the value is changed only for the particular object. See the ex:
class Test{
int a=100; //original value
Test(int b){
this.a=b;
}
Test(){
}
void print(){
System.out.println(a);
}
public static void main(String args[]){
Test t=new Test(9);
Test t2=new Test();
t.print(); //output: 9
t2.print(); //output: 100
}
}