- - PR -
java.lang.OutOfMemoryErrorについて
1
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-11-21 12:08
いつもお世話になっております。
javaに関しましてはservlet・jspのプログラムが組める程度のものです。 現在、windows accessのとあるデータを現行は最大20,000件全データを 読み込みservletの中でcsvファイルとして作成してます。(ローカルに保存) それを今回は50,000件に最大データが増えたことで、csvファイル作成時に servletエラーが発生しました。 以下がエラー内容です。 「Apache Tomcat/4.0.4 - HTTP Status 500 - Internal Server Error type Exception report message Internal Server Error description The server encountered an internal error (Internal Server Error) that prevented it from fulfilling this request. exception javax.servlet.ServletException: サーブレットの実行により例外を投げました at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:243) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:190) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566) at org.apache.catalina.valves.CertificatesValve.invoke(CertificatesValve.java:246) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:564) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943) at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2347) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566) at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:170) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:564) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:170) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:564) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:468) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:564) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943) at org.apache.catalina.connector.http.HttpProcessor.process(HttpProcessor.java:1027) at org.apache.catalina.connector.http.HttpProcessor.run(HttpProcessor.java:1125) at java.lang.Thread.run(Thread.java:536) root cause java.lang.OutOfMemoryError」 java.lang.OutOfMemoryError等で検索をしてみましたが、 jvmの拡張を行う中で、環境変数のCATALINA_OPTで「-Xms 1024 -Xmx 1024 を設定する等があったのですが、 どこに追加すればよいか等よくわからない状態です。 javaのヒープサイズを設定等をすれば解決するのでしょうか? そしてどういう手順で設定すればよいでしょうか? 教えていただけると助かります。 よろしくお願いします。 | ||||||||||||
|
投稿日時: 2006-11-21 12:34
どちらかというと、「全件読み込み」というロジックを変更すべきかと思うのですが。
ヒープサイズの拡大は焼け石に水で、たとえ5万件が通ったとしても、10万件になったらお手上げです。 | ||||||||||||
|
投稿日時: 2006-11-21 12:48
Windowsであれば、catalina.batで起動しているのか、 サービスとして起動しているのかで設定方法が違います。 前者であれば、ユーザーの環境変数として設定するか、 %CATALINA_HOME%\bin\setenv.batに書いておきましょう。 あと、オプションの「-Xms 1024 -Xmx 1024」は間違っています。 正しくは-Xms1024m -Xmx1024mです。
デフォルトの-Xmxは64m程度なので解決する可能性は高いと思いますが、 CSVの出力方法に問題があるはずなので根本的な解決策ではないでしょう。
こんな感じの作りになっていませんか? | ||||||||||||
|
投稿日時: 2006-11-21 13:58
ありがとうございます。
サービスとしては起動しておらず、strat tomcatをクリックして 起動しています。 %CATALINA_HOME%\bin\setenv.batに書き込む内容は、 set CATALINA_OPT=-Xms1024m -Xmx1024mでよいのでしょうか? 申し訳ありません。記述内容も教えていただけると助かります。 検索するといろいろ出てきます。 また、出力方法は確かに全件の場合は、読み込んで最後に処理しております。 以下が大体のコードです。 response.setHeader("Content-Language", "Ja"); response.setContentType("text/csv; charset=Shift_JIS"); //AFixWriter特定の文字化け対策です。 AFixWriter out = new AFixWriter(response.getWriter()); String fileName = "x.csv"; response.setHeader("Content-Disposition", "attachment;filename=\""+fileName+"\""); Vector veca = new Vector(); veca = sqlで読み込み (絞り込み有の場合は絞り込んでますが、全件は50,000件) for( int lp = 0; lp < veca.size(); lp++ ) { Hashtable h = ・・・・・省略 tmpa = 項目セット; tmpStr += ","; : : out.println(tmpa); } out.flush(); out.close(); 一気に読んで溜め込んでflushが悪い感じだと思いますが、 実はもともと私が関わる前からこの組み方でした。 ここから改訂して攻略できるでしょうか? よろしくお願いします。 以上 | ||||||||||||
|
投稿日時: 2006-11-21 14:02
全部読み込んで、全部出力ではなく、読みこみながら出力するようにすれば良いと思います。
| ||||||||||||
|
投稿日時: 2006-11-21 14:13
JDBCでResultsetを使って処理しているのでしたら、
1.Resultsetからデータ取得 2.データ処理 3.ファイル出力 4.1から処理を繰り返す などを行えば、メモリにやさしいコードになると思います。1行1行 やるのがダメでしたら、1、2を数行毎に行うと出力回数を減らせる と思います。 それから、Java1.4以上をお使いでマルチスレッドとは無縁の処理で したら、VectorとHashtableではなく、ArrayListやHashMapを使われ た方が良いですよ。前者は同期処理を行うので、処理がやや重めです。 | ||||||||||||
|
投稿日時: 2006-11-21 14:23
ありがとうございます。
組み替えてやってみます。 ちなみに落ちている箇所はdebugしてみて わかりました。 sqlでvectorにセットしている場所っぽいです。 まだ細かくdebugして行き着いてませんが・・・ もう少し調べて組み替えてみます。 |
1