简体   繁体   中英

Java Destruction of Variables

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?

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

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.

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 ZERO 1 . 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; eg 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.

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.

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");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM