2017-10-18 18 views
0

Tomcat8サーバー用のWebアプリケーションを作成しました。これは、Webベースの小さなゲームです。Tomcat8アプリケーションでJSON Builderがメモリリークの原因となる

私はフラットファイルからMySQLに切り替えたので、javax.json builderには多くの問題があります。

ここに私のコードの一部:

public void saveUserResearch(){ 
    MySQLTable t = SpaceWar.instance().getUserResearchTable(); 

    JsonObjectBuilder mainBuilder = Json.createObjectBuilder(); 
    JsonObjectBuilder subBuilder = Json.createObjectBuilder(); 
    for(UserResearch r : getResearchList()){ 
     int index = r.getIndex(); 
     subBuilder = Json.createObjectBuilder(); 
     subBuilder.add("index", r.getIndex()); 
     subBuilder.add("level", r.getLevel()); 
     subBuilder.add("planed_level", r.getPlanedLevel()); 
     subBuilder.add("player_uuid", r.getPlayerUUIDAsString()); 
     subBuilder.add("unlocked", r.getUnlocked()); 
     subBuilder.add("savedInPlayer", "yes"); 
     mainBuilder.add(index+"", subBuilder.build()); 
    } 
    String q = ""; 
    q += "user_uuid:" + getUUID().toString() + ";"; 
    q += "research_json:" + mainBuilder.build(); 
    t.insertUpdate(q).sync(); 

} 

Mavenの依存性:

<!-- https://mvnrepository.com/artifact/javax.json/javax.json-api --> 
     <dependency> 
      <groupId>javax.json</groupId> 
      <artifactId>javax.json-api</artifactId> 
      <version>1.0</version> 
     </dependency> 
     <!-- https://mvnrepository.com/artifact/org.glassfish/javax.json --> 
     <dependency> 
      <groupId>org.glassfish</groupId> 
      <artifactId>javax.json</artifactId> 
      <version>1.0.4</version> 
     </dependency> 

私はスレッドから2分ごとに呼び出しています。この方法。私は15人のユーザーを持っているので、15回実行されます。 JSONオブジェクトと、私はMySQL DBに保存しているJSONオブジェクトを作成します。だから私は15のインスタンスを期待しています。

問題は数時間後、次のメッセージでTomcatサーバーがクラッシュします。

Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000007b5400000, 1048576, 0) failed; error='Cannot allocate memory' (errno=12) 

There is insufficient memory for the Java Runtime Environment to continue. 
Native memory allocation (mmap) failed to map 1048576 bytes for committing reserved memory. 
An error report file with more information is saved as: 
/tmp/hs_err_pid11069.log 

私はVisualVMを使ってそれを調べて、そこに多くの問題を見つけました。

enter image description here enter image description here

最初の画像では、同じユーザーJSONオブジェクトがあることがわかります。

したがって、mainBuilderとsubBuilderをnullに設定しようとしました。しかし、同じ結果です。また、私はSystem.gc()を呼び出そうとしました。それはものをクリアしません。

は2時間後、この

enter image description here enter image description here

のように見えるし、約5時間後には、これらは私のJVM引数です

メモリ

を使い果たし enter image description here

私はわかりませんなぜビルダーがこのようなメモリリークを引き起こし、私の知識がそれを解決するのに十分ではないのか。多分あなたは私を助けることができます。

私は非常に感謝します。どうもありがとうございました。

私はここからAPIを使用しています:SpiderMySQL そして、javax.json.Json; javax.json.JsonObjectBuilder;

+0

あなたがJsonObjectBuilderのためのサードパーティのlibを使うのですが漏れていませんか?私はtomcatがデフォルト設定に含まれているとは思わない。 – Sorontur

+0

私はjavax.json.JsonObjectBuilderを使用しています。 ... javax.json-api 1.0 – Xearox

+0

thx、私はそれを確認します – Sorontur

答えて

2

私はこの問題を発見したと思います。それはmysqlのlibです! ここでクラスを見てください。https://gitlab.com/Syranda/SpiderMySQL/blob/development/src/main/java/de/syranda/spidermysql/WatchThread.java

ArrayListはスレッドセーフではないため、スレッドセーフではありません。彼らはすでにこのためのバグチケットを持っています。このクラスの組み合わせで

https://gitlab.com/Syranda/SpiderMySQL/blob/development/src/main/java/de/syranda/spidermysql/table/InsertQuery.java

それはconsturctorでこの参照エスケープをすることができます。マルチスレッド環境では非常に悪いことです。これは、奇妙な動作や多分あなたのメモリリークを生成することができます。

この場合、純粋なjdbcに切り替えると、メモリリークが残っているかどうかをテストできます。と私は他のlibを使用することをお勧めします、それは本当にうまく実装されていないようです。

私はJSONのIMPLをテストし、それが何らメモリは

+0

ありがとうございます。これがメモリリークの原因でした。私はこれをAPIで修正しましたが、現在はサーバーのメモリ使用量は常に1GB未満です。悲しいことに私はあなたの答えをアップヴォートすることはできません。 – Xearox

関連する問題