2017-10-18 92 views
0

我已經爲Tomcat8服務器創建了WebApp。這是一個小型的網絡遊戲。JSON Builder在Tomcat8中導致內存泄漏應用

由於我已經從flatfiles切換到MySQL,所以我有很多javax.json構建器的問題。

這裏我的代碼的一部分:

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

我不知道爲什麼建造者會造成這種內存泄漏,我的知識還不足以解決問題。也許你可以幫助我。

我將不勝感激。非常感謝你。

對於MySQL的東西,我從這裏使用的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不是線程安全的。他們已經有了一個bug的票據。

在這一大類的組合: https://gitlab.com/Syranda/SpiderMySQL/blob/development/src/main/java/de/syranda/spidermysql/table/InsertQuery.java

它允許在consturctor的參考逃逸。多線程環境中這是非常邪惡的。它可能會產生奇怪的行爲,也可能導致內存泄漏。

在這種情況下,您可以嘗試切換到純jdbc,以測試是否存在內存泄漏。我建議使用任何其他庫,它似乎沒有得到很好的實施。

我測試了JSON IMPL,它已經沒有內存泄漏

+0

非常感謝你。這是內存泄漏的原因。我已經在API中解決了這個問題,現在服務器的內存使用量始終低於1GB。可悲的是,我不能upvote你的答案只是把它作爲接受的答案。 – Xearox