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?

4

5 に答える 5

4

これらの変数はで作成されるため、パフォーマンスは向上しませんstack

Javaでのオブジェクトの破棄について詳しくは、この記事をお読みください。

オブジェクトを破棄するために使用されるJavaのメソッド

于 2013-01-09T01:11:47.310 に答える
4

Javaはガベージコレクタを使用するため、未使用のオブジェクトは自動的に破棄されます。あなたの例では、ローカル変数のみを使用し、それらはスタックに割り当てられ、これは非常に高速です(そしてここではガベージコレクションは含まれていません)。これらの変数を外部関数(「スコープの上位」)に移動しても効果はありません。

于 2013-01-09T01:12:00.340 に答える
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.

于 2013-01-09T01:45:51.610 に答える
0

この質問への答えは、「nursery gc」と呼ばれる小さなスライスを持っているJavaのガベージコレクションに依存します。これは非常に頻繁に呼び出され、jvmを停止させません。すべてのローカル変数はこの保育園gcに送られます。このメソッドの実行が終了すると、これらの変数はすべてGCに適格です。ナーサリーgcが呼び出されると削除されます。

これらの変数を実行メソッドから移動する方がよいかどうかという質問に答えます。JVMはリリースごとにスマートになっていますが、オブジェクトの作成は、パフォーマンスへの影響が少なくなります。しかし、それでも私はその最小限の影響でさえ感じます。オブジェクトをグローバルにすることに害はないと感じています。

この場合、すべての変数はプリミティブですが、影響はありません。

于 2013-01-09T01:11:21.230 に答える
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");
}
于 2013-01-09T01:18:56.410 に答える