[解決済み] Java のスタックサイズを大きくするには?
質問
私はこの質問を、JVMの実行時呼び出しスタックサイズを増加させる方法を知るためにしました。私はこれに対する答えを得ましたし、Java が大きな実行時スタックが必要な状況をどのように扱うかに関連する多くの有用な答えやコメントを得ました。私は、回答の要約で私の質問を拡張しました。
元々私は、JVM スタック サイズを増加させたいと考えていたので、実行のようなプログラムを
StackOverflowError
.
public class TT {
public static long fact(int n) {
return n < 2 ? 1 : n * fact(n - 1);
}
public static void main(String[] args) {
System.out.println(fact(1 << 15));
}
}
対応するコンフィギュレーション設定は
java -Xss...
コマンドラインフラグを十分大きな値で設定することです。プログラムに対して
TT
上記のプログラムでは、OpenJDKのJVMでこのように動作します。
$ javac TT.java
$ java -Xss4m TT
また、回答の中で指摘されているのが
-X...
フラグは実装に依存していることを指摘しています。私が使っていたのは
java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8.1) (6b18-1.8.1-0ubuntu1~8.04.3)
OpenJDK 64-Bit Server VM (build 16.0-b13, mixed mode)
また、1つのスレッドに対してのみ大きなスタックを指定することも可能です(方法は回答の1つにあります)。これは
java -Xss...
よりも推奨されます。
上のプログラムが具体的にどれくらいの大きさのスタックを必要とするのか気になったので、実行してみました。
n
を増やしました。
-
-Xss4m で十分です。
fact(1 << 15)
-
-Xss5m で十分です。
fact(1 << 17)
-
-Xss7m で十分です。
fact(1 << 18)
-
-Xss9m で十分です。
fact(1 << 19)
-
-Xss18mで十分です。
fact(1 << 20)
-
-Xss35m で十分です。
fact(1 << 21)
-
-Xss68mは
fact(1 << 22)
-
-Xss129mで十分です。
fact(1 << 23)
-
-Xss258m で十分です。
fact(1 << 24)
-
-Xss515m で十分です。
fact(1 << 25)
上記の数字から、Java は上記の関数に対してスタック フレームあたり約 16 バイトを使用しているようで、これは妥当なことです。
上記の列挙には
は十分である
の代わりに
で十分です。
スタック要件が決定論的でないため、同じソースファイル、同じ
-Xss...
で複数回実行すると、成功することもあれば
StackOverflowError
. 例:1 << 20 の場合。
-Xss18m
は10本中7本で十分でしたし
-Xss19m
も常に十分とは言えませんでしたが
-Xss20m
で十分でした(100回実行したうちの100回すべてで)。ガベージ コレクション、JIT のキックイン、または他の何かがこの非決定的な動作を引き起こしているのでしょうか?
で出力されるスタックトレースは
StackOverflowError
(で表示されるスタックトレースは、実行時スタックの直近の1024個の要素のみを表示します。以下の回答は、到達した正確な深さ (1024 よりもはるかに大きい可能性があります) をカウントする方法を示しています。
回答した多くの人が、同じアルゴリズムの代替の、よりスタックハングリーでない実装を考慮することは、良い、安全なコーディングの実践であると指摘しました。一般に、一連の再帰関数を反復関数に変換することは可能です (たとえば
Stack
オブジェクトを使用し、実行時スタックの代わりにヒープ上に配置される)。この特定の
fact
関数については、それを変換するのは非常に簡単です。私の反復バージョンは次のようになります。
public class TTIterative {
public static long fact(int n) {
if (n < 2) return 1;
if (n > 65) return 0; // Enough powers of 2 in the product to make it (long)0.
long f = 2;
for (int i = 3; i <= n; ++i) {
f *= i;
}
return f;
}
public static void main(String[] args) {
System.out.println(fact(1 << 15));
}
}
参考までに、上の反復解法が示すように
fact
関数は65以上の数(実際には20以上でも)の正確な階乗を計算することができません。これはJavaの組み込み型である
long
はオーバーフローしてしまうからです。リファクタリング
fact
を返すように
BigInteger
ではなく
long
のようにすれば、大きな入力に対しても正確な結果が得られます。
どのように解決するのか?
ふむ...私の場合、999MB 未満のスタックで動作します。
> java -Xss4m Test
0
(Windows JDK 7、ビルド 17.0-b05 クライアント VM、および Linux JDK 6 - 投稿されたものと同じバージョン情報)
関連
-
Java コンパイルエラー - スレッド "main" で例外 java.lang.Error: 未解決のコンパイル問題です。
-
あるコードに出会いましたが、何に使うのか理解できません。 List<String> list = new ArrayList<String>() { { a
-
このラインで複数のマーカーを解決する方法
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaでNullPointerExceptionを回避する方法
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] JavaでStringをintに変換するにはどうしたらいいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
undefinedeclipse エラー。この行に複数のアノテーションが見つかりました: - 文字列を型解決に解決できない
-
javaの実行中に「javaの例外が発生しました」と表示された場合はどうすればよいですか?
-
Spring Boot による HTTPS アクセスの設定
-
をインスタンス化することができません。
-
スレッド "main" で例外発生 java.lang.ArrayIndexOutOfBoundsException: 0 at One1.main(One1.java:3)
-
Exception: java.util.NoSuchElementException: 行が見つかりません
-
HttpClientがGZIP形式でない場合の対処法
-
JSPで「リストが型解決できない!」の解決方法
-
Google Chromeのエラー「Not allowed to load local resource」の解決策について
-
[解決済み] JavaでNoClassDefFoundErrorが発生するのはなぜですか?