Java が未使用の変数をどのように処理するかについて質問があります。
次のコードがあるとしましょう:
int notUsedVariable = aMethodThatExecutesSomethingImportantAndReturnsInt(someParameter);
次に、コードで notUsedVariable を使用することはありません。その変数は実際に保存されますか、それとも Java はコンパイル時に変数を無視するほどスマートですか?
ありがとう!
私の観察では、次の場合、javac は未使用の変数のストア操作を省略できる可能性があります。
final
、宣言で初期化されます。-g:vars
( )でコンパイルすると-g:vars
、javac はデバッグ目的で変数のロードとストアをそのまま保持します。非最終変数を削除の対象と見なしていないようです。
自分でテストしてください。JDK 7 での私の結果は以下のとおりです。結果は、JDK 8 EAP と同じでした。
入力:
class MyTest {
public static void main(String... args) {
int a = 1;
}
}
出力:
public static void main(java.lang.String... p0);
Flags: PUBLIC, STATIC, VARARGS
Code:
stack=1, locals=2, arguments=1
0: iconst_1
1: istore_1
2: return
入力:
class MyTest {
public static void main(String... args) {
final int a = 1;
}
}
出力:
public static void main(java.lang.String... p0);
Flags: PUBLIC, STATIC, VARARGS
Code:
stack=1, locals=2, arguments=1
0: return
他の人が言ったように、どちらの場合でも、JIT オプティマイザーが不要なストア操作を省略することを期待します。
javac は多くの最適化を実行しません。一方、JIT は、
http://www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/をチェックしてください。
ここに引用があります。
さらに重要なことに、javac コンパイラは、ループ展開、代数的単純化、強度削減などの単純な最適化を実行しません。これらの利点とその他の単純な最適化を実現するには、プログラマは Java ソース コードでそれらを実行する必要があり、javac コンパイラに依存して実行する必要はありません。
これについてさらに詳しく説明している別のスレッドもあります。 Javaコンパイラによる最適化
例をコンパイルしましょう
public class Test {
public static void main(String... args) {
int a = 1;
}
}
我々が得る
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String...);
Code:
0: iconst_1 // push integer 1 on stack
1: istore_1 // pop integer from stack, store it in local variable 1
2: return
}
ローカル変数が削除されていないことがわかります。保管されていました。
実行時に最適化が行われる可能性があることに注意してください。
変数のスコープに基づいて格納され、スコープが終了すると、ガベージ コレクションによって変数が使用するメモリがクリーンアップされます。
クラス変数とローカル変数の Test クラスを 1 回編集し、Eclipse を使用してクラス ファイルを検査しました。(Eclipse は、変数が使用されていないと文句を言います。)
// Compiled from UserLoadTest.java (version 1.6 : 50.0, super bit)
public class org.dev.user.UserLoadTest extends org.test.BaseTestCase {
// Field descriptor #6 I
public int myVariable;
...クラスファイルがこれを認識していることがわかります
@org.junit.Test
public void testBasicUserLoad() throws java.io.IOException, org.custommonkey.xmlunit.exceptions.XpathException;
0 aload_0 [this]
1 ldc <String "user_01.xml"> [24]
...
org.custommonkey.xmlunit.XMLAssert.assertXpathEvaluatesTo(java.lang.String, java.lang.String, org.w3c.dom.Document) : void [85]
223 aload_2 [reloaded]
224 invokevirtual org.testHarness.Result.getDocument() : org.dom4j.dom.DOMDocument [81]
227 astore_3 [d]
228 return
行 224 は、次を使用した変数の単純な宣言です。
Document d = reloaded.getDocument();
これは何もしませんd
が、変数が作成されたことをクラスファイルが認識します。