2

Java が未使用の変数をどのように処理するかについて質問があります。

次のコードがあるとしましょう:

int notUsedVariable = aMethodThatExecutesSomethingImportantAndReturnsInt(someParameter);

次に、コードで notUsedVariable を使用することはありません。その変数は実際に保存されますか、それとも Java はコンパイル時に変数を無視するほどスマートですか?

ありがとう!

4

6 に答える 6

5

私の観察では、次の場合、javac は未使用の変数のストア操作を省略できる可能性があります

  1. 変数は としてマークされfinal 宣言で初期化されます。
  2. ローカル変数のデバッグ情報を使用してコンパイルしていませ-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 オプティマイザーが不要なストア操作を省略することを期待します。

于 2013-06-19T19:16:25.253 に答える
2

javac は多くの最適化を実行しません。一方、JIT は、

http://www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/をチェックしてください。

ここに引用があります。

さらに重要なことに、javac コンパイラは、ループ展開、代数的単純化、強度削減などの単純な最適化を実行しません。これらの利点とその他の単純な最適化を実現するには、プログラマは Java ソース コードでそれらを実行する必要があり、javac コンパイラに依存して実行する必要はありません。

これについてさらに詳しく説明している別のスレッドもあります。 Javaコンパイラによる最適化

于 2013-06-19T18:45:45.097 に答える
2

例をコンパイルしましょう

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        
}

ローカル変数が削除されていないことがわかります。保管されていました。

実行時に最適化が行われる可能性があることに注意してください。

于 2013-06-19T18:46:15.423 に答える
0

変数のスコープに基づいて格納され、スコープが終了すると、ガベージ コレクションによって変数が使用するメモリがクリーンアップされます。

クラス変数とローカル変数の 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が、変数が作成されたことをクラスファイルが認識します。

于 2013-06-19T18:40:09.790 に答える