JVMローカル変数表

1805 ワード

ローカル変数表はJVMスレッドスタックの各frameの中の一つの構成要素(詳細は「JVMスレッドスタック」を参照)であり、現在の方法の実行中でも依然として有効なローカル変数が格納されている。ローカル変数テーブルの長さはクラスコンパイル中に確定できます。これはframe初期化に有利です。
    void fun () {
        int a = 0;
        int b = 1;
        int c = 2;
    }
    funの局所変数表長は4である(JVM仕様によると、最初はthisポインタ)
    void fun2() {
        {
            int a = 0;
        }
        int b = 1;
        int c = 2;
    }
    funの局所変数表長は3であり、これは局所変数テーブル中のスロットビットが多重化されるからである。プログラムがb=1に到達すると、a変数の宣言周期は終了し、b変数はa変数の動作を占有します。SLot多重の特徴のために、面白い問題が出てきます。
    public static void main(String[] args) throws Exception {
        {
            byte[] _64M = new byte[1024 * 1024 * 64];
        }
        System.gc();
        Thread.sleep(1000);
        System.gc();
        Integer a = null;
        System.gc();
    }
    -verbose:gcを使ってgcロゴを打ち上げると、次のように見えます。    [GC(System.gc()   67502 K->66452 K(123904 K)、0.0011957 secs)    [Full GC(System.gc()   66452 K->66331 K(123904 K)、0.005344 secs)    [GC(System.gc()   66987 K->66363 K(123904 K)、0.0007278 secs)    [Full GC(System.gc()   66363 K->66331 K(123904 K)、0.005632 secs)    [GC(System.gc()   66331 K->66331 K(123904 K)、0.0011248 secs)    [Full GC(System.gc()   66331 K->795 K(123904 K)、0.005 secs)    初めてgcは64 Mの配列を回収しませんでしたが、_64 Mのライフサイクルはもう終わりました。1 s寝ても回収できません。スペースはそのまま1 sを占めました。    この現象を説明するのはJVM回収対象の条件から始まります。JVMは局所変数を回収する前提として、局部変数表にその対象の参照がない(配列エンティティがスタックしている)が、初めてgcを行った時、_64 Mオブジェクトは無効になりましたが、彼の参照はまだ部分変数テーブルにありますので、gcは回収できません。その後、勝手に一つの変数を宣言して、局部変数表の中の_を突き落としました。64 Mの引用はリサイクルすればいいです。    このような方法はいくつかのオープンソースコードの中にも見られます。オブジェクトのライフサイクルが終了し、方法内に時間がかかります。実際にJITコンパイルではnullの割り当て操作は消去されますが、JIT後のコードは正しく回収されます。このようなnullの割り当ては、JIT規格に達していないコール回数で効果があります。   
参考:https://blog.csdn.net/kevin_luan/articale/detail/22986081