- PR -

java.lang.OutOfMemoryErrorについて

1
投稿者投稿内容
りゅう
会議室デビュー日: 2005/10/12
投稿数: 3
投稿日時: 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のヒープサイズを設定等をすれば解決するのでしょうか?
そしてどういう手順で設定すればよいでしょうか?
教えていただけると助かります。

よろしくお願いします。

mio
ぬし
会議室デビュー日: 2005/08/25
投稿数: 734
お住まい・勤務地: 神奈川県
投稿日時: 2006-11-21 12:34
どちらかというと、「全件読み込み」というロジックを変更すべきかと思うのですが。
ヒープサイズの拡大は焼け石に水で、たとえ5万件が通ったとしても、10万件になったらお手上げです。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-11-21 12:48
引用:

りゅうさんの書き込み (2006-11-21 12:08) より:
jvmの拡張を行う中で、環境変数のCATALINA_OPTで「-Xms 1024 -Xmx 1024
を設定する等があったのですが、
どこに追加すればよいか等よくわからない状態です。



Windowsであれば、catalina.batで起動しているのか、
サービスとして起動しているのかで設定方法が違います。

前者であれば、ユーザーの環境変数として設定するか、
%CATALINA_HOME%\bin\setenv.batに書いておきましょう。

あと、オプションの「-Xms 1024 -Xmx 1024」は間違っています。
正しくは-Xms1024m -Xmx1024mです。

引用:

javaのヒープサイズを設定等をすれば解決するのでしょうか?



デフォルトの-Xmxは64m程度なので解決する可能性は高いと思いますが、
CSVの出力方法に問題があるはずなので根本的な解決策ではないでしょう。

コード:
String csv = "";
while (最後のエントリまで) {
  String line = 一行の変換処理();
  csv += line;
}
response.getWriter().print(csv);



こんな感じの作りになっていませんか?
りゅう
会議室デビュー日: 2005/10/12
投稿数: 3
投稿日時: 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が悪い感じだと思いますが、
実はもともと私が関わる前からこの組み方でした。
ここから改訂して攻略できるでしょうか?

よろしくお願いします。
以上
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2006-11-21 14:02
全部読み込んで、全部出力ではなく、読みこみながら出力するようにすれば良いと思います。
小僧
ぬし
会議室デビュー日: 2002/08/14
投稿数: 526
投稿日時: 2006-11-21 14:13
JDBCでResultsetを使って処理しているのでしたら、
1.Resultsetからデータ取得
2.データ処理
3.ファイル出力
4.1から処理を繰り返す

などを行えば、メモリにやさしいコードになると思います。1行1行
やるのがダメでしたら、1、2を数行毎に行うと出力回数を減らせる
と思います。
それから、Java1.4以上をお使いでマルチスレッドとは無縁の処理で
したら、VectorとHashtableではなく、ArrayListやHashMapを使われ
た方が良いですよ。前者は同期処理を行うので、処理がやや重めです。

りゅう
会議室デビュー日: 2005/10/12
投稿数: 3
投稿日時: 2006-11-21 14:23
ありがとうございます。
組み替えてやってみます。
ちなみに落ちている箇所はdebugしてみて
わかりました。
sqlでvectorにセットしている場所っぽいです。
まだ細かくdebugして行き着いてませんが・・・

もう少し調べて組み替えてみます。

1

スキルアップ/キャリアアップ(JOB@IT)