0

再帰的メソッド呼び出しの正確にどの部分がスタックに寄与するのでしょうか?たとえば、返されたオブジェクト、引数、ローカル変数などでしょうか?

StackOverflowException が発生する前に、限られたメモリで Android アプリケーションが実行できる再帰のレベルを最適化しようとしています。

前もって感謝します。

4

2 に答える 2

0

各メソッドには、引数とローカル変数に必要なスタックと、式の評価に必要なスタックの2つのスタックフレームサイズが関連付けられています。戻り値は、式の評価に必要なスタックの一部としてのみカウントされます。JVMは、実行時にメソッドがこれらのサイズを超えていないことを確認できます。

変数と式の評価に必要なスタックの正確な量は、バイトコードコンパイラに依存します。たとえば、ライフタイムが重複しない変数間でローカル変数スロットを共有できることがよくあります。

于 2012-08-19T23:00:14.733 に答える
0

スタック スペースが不足している場合は、スタックの使用を最適化しないでください。これを行うと、同じ問題が後で戻ってきて、入力セットが少し大きくなったり、別の場所から呼び出されたりすることになります。そして、ある時点で、解決しようとしている問題のために消費できる理論的または実際的な最小スペースに達します。代わりに、問題のあるコードを変換して、マシン スタック以外のコレクション (たとえば、ヒープ割り当てスタックまたはキュー) を使用します。そうすることで非常に醜いコードになることもありますが、少なくともクラッシュすることはありません。

しかし、質問に答えるには: 通常、名前を付けたものはすべてスタック スペースを取ることができ、一時的な値もスペースを取ることができます (そのため、ローカル変数を保存するためだけに式を入れ子にすることは役に立ちません)。これらの一部は、呼び出し規約に応じてレジスタに格納されますが、とにかくスピル (*) する必要がある場合があります。ただし、呼び出し規約に関係なく、これは数バイトしか節約できず、通常、呼び出し中に呼び出し先が自由にレジスタを制御できるため、呼び出しのためにすべてをスピルする必要があります。したがって、スタックがオーバーフローした時点で、スタックはパラメーター、ローカル変数、および以前の呼び出しの一時的なもので実際に混雑しています。同時に必要でない場合は、完全に最適化されていないか、スタック スロットを共有しているものもあります。最終的に、これは JIT コンパイラ次第です。

(*) スピル: レジスターが別の目的で必要なため、値をレジスターからメモリー (つまり、スタック) に移動すること。

于 2012-08-19T22:56:19.273 に答える