4

Java 関数内のステートメントの場合:

Xxx xxx = new Xxx() {
    public Abc abc(final Writer out) {
        return new SomeFunction(out) {
            boolean isDone = false;
            public void start(final String name) {
                /* blah blah blah */
            }
        };
    }
};

関数を含め、どの変数がヒープに配置され、どの変数がスタックに配置されますか?

私がこれを尋ねている理由は、JVM のセグメンテーション違反です。

kernel: java[14209]: segfault at 00002aab04685ff8 rip 00002aaab308e4d0 rsp 00002aab04685ff0 error 6

00002aab04685ff8近くに00002aab04685ff0ある場合、スタックの成長が速すぎるようです。コードのこの部分を調査しようとしましたが、この関数を何度も呼び出すと問題が発生する原因になるのではないかと疑っています。ヒープ上のいくつかの変数によって参照されている場合、スタックがクリアされない可能性はありますか?

4

2 に答える 2

5

特定のオブジェクトがヒープに入るかどうかという問題は、少し複雑です。

一般に、Java では、すべてのオブジェクトがヒープに割り当てられます。これは、メソッドがオブジェクトへのポインターを返したり格納したりする可能性があるためです。オブジェクトがスタックに配置されていた場合、次にスタック フレームがそこに配置されたときにオーバーライドされます。

ただし、HotSpot JIT コンパイラはEscape Analysisと呼ばれるものを実行します。この分析では、メソッドのコードを調べて、オブジェクトがメソッドのスコープを「エスケープ」しているかどうかを調べます。オブジェクトがエスケープしない場合、コンパイラはそれを安全にスタックに割り当てることができます。

ウィキペディアには、Java での Escape Analysisに関する詳細情報と、マルチスレッドとロックに関する情報があります。


スタック オーバーフローについて: コール スタックのスタック フレームは、メソッドの終了後に常に削除されます。実際には、明示的に削除する必要さえありません。次のフレームは、以前のフレームを上書きします。

また、他の言語 (C など) では、非常に大きなオブジェクトをスタックに置くことでスタックがオーバーフローする可能性がありますが、これが Java で発生する可能性はないと思います。Sun (Oracle) のエンジニアは、VM が巨大なオブジェクトをスタックに格納しないように賢くいることを期待しています。

したがって、スタック オーバーフローが発生する唯一の可能性は、ネストされたメソッド呼び出しが多すぎることです。スタック スペースは「通常の」メソッド呼び出しのネストを処理するのに十分な大きさであるため、スタック オーバーフローは通常、コード内の無限 (または非常に大きな) 再帰を示します。

于 2012-05-07T12:11:15.850 に答える
0

name、、、および匿名isDoneoutABC「ポインタ」someFunctionはすべてスタック上にあります。残りはヒープに行きます。

于 2012-05-07T11:50:21.617 に答える