2017-10-18 93 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