1

I was asked this by a fellow developer recently, and could not provide the answer...

In Java, how/when are variables disposed of? Are they?

Let's say we have a run() method that gets called 50-75 times per second (heavily simplified example)...

public void run() {
    long lastTime = System.nanoTime();
    double unprocessed = 0;
    int ticks = 0;
    int frames = 0;
    double nsPerTick = 1000000000.0 / 60.0;
    long now = System.nanoTime();
    unprocessed += (now - lastTime) / nsPerTick;
    lastTime = now;

    ticks++;
    tick();
    unprocessed -= 1;
}

Would bringing those variables (lastTime, unprocessed, ticks, etc.) into a higher level of scope make the program run better/more efficiently--to a place where they are not created and used multiple times per second?

benny.bennett
  • 700
  • 1
  • 8
  • 25
  • 2
    [This](http://stackoverflow.com/questions/4138200/garbage-collection-on-a-local-variable) might be of some help – MadProgrammer Jan 09 '13 at 01:11
  • 3
    *Variables* aren't disposed of. They have a defined "scope" and disappear when they exit the scope. (*Objects*, on the other hand, are garbage-collected.) – Hot Licks Jan 09 '13 at 01:12

5 Answers5

4

It won't give you any performance improvement as those variables are created in stack.

Read this article to get more about Object destructions in Java:

What method in Java is used to destroy your objects

Community
  • 1
  • 1
Archer
  • 5,073
  • 8
  • 50
  • 96
  • 1
    And it should be noted that, unlike Pascal or Algol, Java does not have "lexical scope", nor does it have "dynamic scope" similar to Perl or Lisp. Variables are either local scope, instance scope, or static (class) scope. – Hot Licks Jan 09 '13 at 01:18
4

Java uses a garbage collector, so unused objects are disposed of automatically. In your example you use only local variables, they are allocated on the stack and this is very fast (and no garbage collection is involved here). Moving these variables to the outer function ("higher in the scope") would not help.

mabn
  • 2,473
  • 1
  • 26
  • 47
2

In Java, how/when are variables disposed of? Are they?

First, lets get something clear. In Java, there are things called variables, and there are things called objects. Variables and objects are not the same thing.

A variable in Java is always part of something else:

  • An local variable is part of the state of a method call. It gets disposed of when it goes out of scope. That typically means when the method call ends and the method call's stack frame gets popped from the call stack.

  • An instance variable (or field or attribute) is part of an object. It gets disposed of when the object gets disposed of.

  • A static variable (or class variable) is part of a class, and will only get disposed of if the class is unloaded.

In your example, all of the variables are local variables, and will be "disposed of" when the current call to the run() method returns (or terminates due to an exception).

Would bringing those variables (lastTime, unprocessed, ticks, etc.) into a higher level of scope make the program run better/more efficiently--to a place where they are not created and used multiple times per second?

It wouldn't help. The incremental cost of creating or disposing of a local variable is ZERO1. And the cost of using a local variable is (if anything) less that the cost of using an instance variable. The only cost might be in initializing it, but you would incur that cost anyway; e.g. in re-initializing an instance variable on each method call.

Indeed, turning local variables into instance variables could actually be a bad thing. It would mean that the method now uses object variables to represent its state, making it non-reentrant. (It is unclear whether that matters here. It depends on whether the run() method is used in a way that requires it to be reentrant ... and typically that is not the case.)


1 - That's slightly over-simplified. If you have a large enough number of local variables and/or a deeply recursive method, then it is possible that you will need to use a larger-than-normal thread stack size. That extra memory usage would be a cost.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • This was a very informative and complete answer. Thank you very much. Do you know of any resources I could refer to to gain more insight into Java memory management? – benny.bennett Jan 09 '13 at 02:24
0

The answer to this question depends on Java's Garbage collection which is having a smaller slice called as "nursery gc" which gets invoked very frequently and does not cause jvm halt. all the local variables goes to this nursery gc. When this method execution finishes; all these variables are eligible for GC; and are removed when nursery gc is invoked.

Answering your question whether moving these variables out of run method be better. Though JVM is getting smarter with every release; creation of objects is less impact on performance. But still I feel even with that minimal impact; I feel there is no harm in making objects global.

Though in this case all the variables are primitive; it will not create any impact.

Deepak Singhal
  • 10,568
  • 11
  • 59
  • 98
  • 4
    Primitives declared within method scope are created on the stack and never garbage-collected. – us2012 Jan 09 '13 at 01:12
  • Sorry my mistake; I didnt noticed that all are primitives. I just concentrated on Variables and gave a generic answer considering them as Objects. – Deepak Singhal Jan 09 '13 at 01:18
  • 1
    You conflated the terms "variable" and "object". They are entirely different and distinct, and it's important to understand the distinction. – Hot Licks Jan 09 '13 at 01:20
0

Id depends on JVM run mode, and JVM version.

But most JVM version will perform like this:

When JVM run on -client mode the code will run line by line.

But when JVM run on -server mode, code will be optimize:

Suppose the tick() method is:

public void tick(){
   System.out.println("tick");
}

Final code after optimize maybe:

public void run() {
  long lastTime = System.nanoTime();
  int ticks = 0;
  int frames = 1;
  double unprocessed = (System.nanoTime() - lastTime) / 16666666.66 -1 ;
  // tick method will inline here instead of invoking tick();
  System.out.println("tick");
}
lichengwu
  • 4,277
  • 6
  • 29
  • 42
  • This is not true. -client and -server have different optimization strategies. see http://stackoverflow.com/questions/198577/real-differences-between-java-server-and-java-client – mabn Jan 09 '13 at 01:23
  • @mabn YES, the optimization is called `escape analysis` and `method inline` using above. – lichengwu Jan 09 '13 at 01:31
  • And from memory, if the method gets called enough times then the JVM(with either option) will speed it up. Say if the method does nothing externally(such as `void func(){int i=0;i++;i--;}`)then after a while the JVM will optimise the code so the function effectively does `void func() {}` and remove the function call altogether. – Opal Jan 09 '13 at 01:34