質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

2804閲覧

JavaのOutOfMemoryError

dttornado

総合スコア20

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2016/07/10 00:29

編集2016/07/10 12:24

###前提・実現したいこと
ルーム機能のないチャットアプリにおいてクライアントアプリからソケット通信を用いて送られてきたメッセージを処理するサーバアプリ

###発生している問題・エラーメッセージ

クライアントアプリごとにメッセージを貯めるスレッドのオブジェクトを生成するが、スレッドのrunメソッドのwhileループでメッセージを取得しようとするところでOutOfMemoryError:Java heap spaceがでてしまう、また、オブジェクトのコレクションにためたメッセージを他のスレッドから処理できなくなってしまう
原因と対策を教えてください
よろしくお願いします
追記:スタックトレース
Exception in thread "Thread-4" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:261)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
at java.util.ArrayList.add(ArrayList.java:458)
at GetMsgThread.run(NChat.java:176)

追記:原因は不明のままですが、対処法については判明しました。SrcThreadのwhileループの1つ下のブロック、つまりforループの前にSystem.out.println()などのなんらかのメソッドを呼び出すと正常に作動することが分かりました。
しかし原因については一切の見当が付きません
###該当のソースコード
Java

import 色々 class NChatC{ staticな変数色々定義 mainメソッドでコンストラクタ呼び出し コンストラクタでフレーム作成、AcceptThread及びSrvThreadをstart() } class AcceptThread extends Thread{ run(){ ServerSocketをwhileループ内で作成しaccept()され されたらaddMember()に引数でわたす } addMember(Socket sock){ クライアント毎にsocket,inputstream,outputstrea m,ユーザー名、GetMsgThread(inpustreamで取得した文字列をためるスレッド)のオブジェクトのコレ クションを新たなメンバー用に追加し、新たなメン バーに現在の参加メンバーを通知し、現在のメンバ ーに新たな参加者を通知する } } //問題が発生するスレッド //クライアントごとにメッセージをためる class GetMsgThread extends Thread{ ArrayList<String> newMsg=new ArrayList<String>(); Inp in; boolean flag=true; public GetMsgThread(Inp inp){ in=inp; } public void run(){ while(flag){ newMsg.add(in.inp()); } } public String getMsg(){ String msg=newMsg.get(0); newMsg.remove(0); return msg; } } //GetMsgThreadで入手した文字列を処理するスレッド //socketVはソケットのコレクション //gmtVはGetMsgThreadのオブジェクト SrvThread{ run(){ while(true){ for(int i=0;i<NChat.socketV.size();i++){ String str=""; if(NChat.gmtV.get(i).newMsg.size()!=0){ str=NChat.gmtV.get(i).getMsg} } strの処理 } } } class Out{ OutputStreamをバッファとしてためて出力 } class Inp{ InputStreamをバッファにためて inp()メソッドで返す } //Inpクラスの内容追記 class Inp{ String str=null; BufferedReader br; Inp(InputStream ist){ try{ InputStreamReader isp = new InputStreamReader(ist); br = new BufferedReader(isp); }catch(Exception e){ System.err.print(e); } } String inp(){ try{ str = br.readLine(); }catch(Exception e){ System.err.print(e); } return str; } void inpcls(){ try{ br.close(); }catch(Exception e){ System.err.println(e); } } }

###試したこと
オブジェクトやスレッドが解放されてないのかと思い、通信終了時に明示的に終了するようにした(そもそも通信終了処理ができない時点でエラーが発生しているので効果はなかった)

###補足情報(言語/FW/ツール等のバージョンなど)
開発当初はこのようなエラーも出ず、最近になってからでるようになった

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

eripong

2016/07/10 08:48

in.inp()の実装内容をできるだけ提示してください。OutOfMemoryErrorのスタックトレースも載せてもらえませんか?
dttornado

2016/07/10 09:10

実装内容、スタックトレース追記させていただきました。
dttornado

2016/07/11 02:56

解決しました。コメントありがとうございました。
guest

回答2

0

自己解決

なんとなく原因が分かりました。
私はメッセージを処理するスレッドをwhileループで回し続けたまま休ませることをしていなかったのですが(タイムラグが発生すると思い)、そのままだとループに次ぐループでうまく処理をこなせなくなってしまうようです。特にループは全てメッセージについて扱うものでしたからメッセージ自体が自身の処理を行うことができなくなってしまいなんらかの形で処理が滞って本来起こるはずのないOutOfMemoryエラーがでてしまったのかな、と思います。
対処法としては、スレッドを休ませることです。基本ですが大事ですね。これからはもうちょっとJVMに優しくなりたいです。

投稿2016/07/11 02:55

dttornado

総合スコア20

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

java

1while(flag){ 2 newMsg.add(in.inp()); 3}

これいつflagがfalseになるんでしょうね。

投稿2016/07/10 07:15

ozwk

総合スコア13528

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dttornado

2016/07/10 08:27

返信ありがとうございます 説明不足で申し訳ございません。flagは、クライアントから切断用のメッセージが来るか切断されたらfalseになるようにstrの処理の部分で設定してあります。ただし、そのメッセージが、処理する部分まで到達していません。クライアントからのメッセージはGetMsgThreadまで到達していることは確認済みですがその後行方がわからなくなり、更にOutOfMemoryErrorも出てしまう次第です
dttornado

2016/07/11 02:56

解決しました。回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問