2016-05-04 8 views
2

1 MBのスタックサイズを持つ通常の64ビットホットスポットJVMがあります。今、私は3022の親の階層を持つオブジェクトをシリアル化しようとしていましたが、これは私にSO(皮肉)例外を与えています。JVMのスタックサイズの仕様

ここにいくつかのコードです:

while(epc.getParent()!=null){ 

     epc=epc.getParent(); 
     count++; 
    } 
    print(count);//3022 

上記のコードは、単に階層を伝えることですが、私はObjectOutputStreamの上にepcオブジェクトをシリアル化しようとすると、実際の問題が発生します。

質問スタックフレームのサイズがわからないので、JVMで1 MBのスタックサイズとは何ですか? -Xss3000kでコードを正常に実行したため、1スタックフレームあたり1KBではないと確信しています。

もう1つの質問ですが、-Xss3000kのJVMオプションを設定すると、すべてのスレッドに3000kのスタックサイズがありますか?

+0

「JVMの1 MBのスタックサイズの状態は何ですか?」について詳しく説明してください。それはあまり明確ではありません。 –

+0

そのコードは、多くのスタックスペースを消費するようには見えません。 'getParent()'はどのように機能しますか? 「オブジェクトを直列化する」とは、「ObjectOutputStreamに書き込む」という意味ですか? – Thilo

+0

@RazvanManolescu親の階層が3022の親を持つオブジェクトの直列化を1 MBで処理できるかどうかを知りたいですか? –

答えて

10

質問、私は考えどのようなサイズのスタックフレームを持っていないとして、JVMで1メガバイトのスタックサイズの状態を何?

1 MBのデフォルトのスレッドスタックサイズは、すべてのスレッドがデフォルトで1 MB(1048576バイト)のスタック領域を持つことを意味します。ただし、スタックサイズ引数を指定できるコンストラクタThreadのいずれかを使用してコードがスレッドを作成する場合は例外です。

スタックフレームのサイズは、呼び出されるメソッドによって異なります。メソッドのパラメータとローカル変数を保持する必要があるため、フレームサイズはそのサイズに依存します。各フレームはまた、保存されたフレームポインタと保存されたリターンアドレスを保持するために2つの余分な単語を必要とします。

再帰アルゴリズムでは、1回の「再帰レベル」で複数のスタックフレームを使用できます。 writeObjectため(ジャワ8)には、使用されるアルゴリズムは再帰的であり、シリアル化されたデータ構造のレベルごとに4つのフレーム典型的にあります

writeObject0 
writeOrdinaryObject 
writeSerialData 
defaultWriteFields 
writeObject0 
etcetera 

実際のフレームサイズはプラットフォームに依存するであろうが原因コンパイラの違い、 ObjectInputStream/ObjectOutputStreamの実装の変更が含まれます。最初の原則からフレームサイズを予測しようとするのではなく、必要なスタックスペースを(おおまかに)測定しようとするほうがよいでしょう。

私はJVMオプション-Xss3000kを置くと、もう1つ質問がありますが、すべてのスレッドは3000kのスタックサイズを持っていますか?

はい...上記で説明した以外は例外です。

ジレンマの可能な解決策の1つは、シリアル化に使用する巨大なスタックを持つ特別なスレッドを作成することです。デシリアライズには、巨大なスタックを持つ同様のスレッドが必要です。スレッドの残りの部分では、デフォルトのスタックサイズは問題ありません。

他の可能な解決策:

  • あなたが深い再帰を取得しないように配列にあなたのEPCのオブジェクトの親構造を平坦にするwriteReplacereadResolveメソッドを実装します。 (もちろん、平坦化/ unflatteningは非再帰的に実行する必要があります。)

  • あなたはエトセトラ、writeObject呼び出す以前と同じ平坦化を行います。

  • 異なるシリアル化メカニズムを使用することも、カスタムの可能性もあります。

+1

スタックのサイズを上げることによってオブジェクトグラフをシリアル化するために管理するには、デシリアライズの最後にスタックサイズを上げる必要があります。正確な要件は実装固有のものになります。 – Holger

+0

@Holger良い点。更新しました。 –

2

-Xss3000kのJVMオプションを設定すると、すべてのスレッドに3000kのスタックサイズがありますか?

新しいスレッドにはa constructor to specify the stack sizeがあります。その特別なコンストラクタを使用しないすべてのスレッドは、JVMオプションで指定されたデフォルトのスタックサイズを取得します(明示的に作成しない限り、すべてのスレッドをカバーします)。

アプリケーションでスレッドを大量に必要としない場合は、問題が発生していない可能性が高く、最も簡単な解決策です。

もしそうでなければ、特に深く再帰的なシリアライゼーションコードを実行するために、このようなビッグスタックスレッドを構築したいかもしれません。あなたはそれをExecutorにまとめ、アプリケーションコードを呼び出すことができます。

JVMの1 MBのスタックサイズは、どのようなサイズのスタックフレームではわからないのですか?

これは確かに動きのあるターゲットです。これを構成可能にして、実験が良い設定が何であるかを教えてください。このコンストラクタの動作のプラットフォーム依存性のために、細心の注意は、その使用中に行使されなければならない原因

さえ、Javadocは

を言います。特定の計算を実行するのに必要なスレッドスタックサイズは、JREの実装ごとに異なる可能性があります。このバリエーションに照らして、スタック・サイズ・パラメーターを慎重に調整する必要があり、アプリケーションを実行するJRE実装ごとにチューニングを繰り返す必要があります。