これらの2つのJavaメソッド呼び出しのいずれかが、プロセッサ時間、メモリ割り当て、ガベージコレクションの点でまったく異なる動作をするかどうかを知りたいです。
SomeObject myObj = new SomeObject();
myObj.doSomething();
対。
new SomeObject().doSomething();
これらの2つのJavaメソッド呼び出しのいずれかが、プロセッサ時間、メモリ割り当て、ガベージコレクションの点でまったく異なる動作をするかどうかを知りたいです。
SomeObject myObj = new SomeObject();
myObj.doSomething();
対。
new SomeObject().doSomething();
生成されたバイトコードを見る:
// code 1
new SomeObject().doSomething();
// bytecode 1
0: new #2; //class SomeObject
3: dup
4: invokespecial #3; //Method SomeObject."<init>":()V
7: invokevirtual #4; //Method SomeObject.doSomething:()V
10: return
これにはさらに2つの指示があることがはっきりとわかります。
// code 2
SomeObject myObj = new SomeObject();
myObj.doSomething();
// bytecode 2
0: new #2; //class SomeObject
3: dup
4: invokespecial #3; //Method SomeObject."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4; //Method SomeObject.doSomething:()V
12: return
これらの手順は非常に冗長で、最適化が容易なようです。必要に応じて、JITコンパイラがそれらを処理すると思います。
違いは正確に2つのJVMバイトコードであり、これは1つの追加のマシン命令に変換されます。これはJITが最適化する可能性があります(変数で他に何もしない場合)。
いいえ。
myObjが他の用途に使用されていないと仮定すると、質問の性質から推測できるように、違いは見られないはずです。いずれにせよ、このようなオーバーヘッドについて心配する必要があるのは、このコードが何度も実行されているループ内にある場合だけです。その場合、JavaのJIT最適化は非常に適切に処理され、違いは見られないはずです。私はこのコードがあなたの2番目の例のように書かれているのを見たいのですが、それは私だけです。
生成されるバイトコードは異なる場合がありますが、これはjitコンパイラーが最適化するのが簡単なことの1つであると思います。実際に何をするかに応じて、オブジェクトの作成でさえ完全に最適化することができます。
2つの違いは、myObj
参照がクリアされておらず、オブジェクトpath to root
が割り当てられているオブジェクトの一部がガベージコレクションされないことだけです。
最初の例は少し効率が悪くなります。最初の例では、オブジェクト参照は関数または囲んでいるブロックの終わりまで保持されます。2番目の例では、呼び出しが完了すると、オブジェクト参照をガベージコレクションに使用できるようになります。もちろん、実際にはガベージコレクションではない場合があります。
生成されたバイトコードを確認していません。Javaが参照を保持する方法にはおそらく違いがありますが、どちらの場合でも、それは些細なことだと思います。