JSON Builder导致Tomcat8应用程序中的内存泄漏

时间:2017-10-18 03:38:04

标签: java json memory-leaks out-of-memory tomcat8

我为Tomcat8服务器创建了一个WebApp。这是一款基于网络的小游戏。

由于我已从flatfiles切换到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

我不确定为什么构建器会导致这种内存泄漏,而且我的知识还不足以解决它。也许你可以帮助我。

我将非常感激。非常感谢你。

对于MySQL的东西我从这里使用API​​:SpiderMySQL 和javax.json.Json; javax.json.JsonObjectBuilder;

1 个答案:

答案 0 :(得分: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,它有无内存泄漏