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

JSON Builder cause memory leak in Tomcat8 Application

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

自从我从平面文件切换到 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 数据库的 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 对其进行研究,但发现了很多问题。

在第一张图片中,您可以看到有相同的用户 json 对象。

所以我尝试将mainBuilder和subBuilder设置为null。但结果相同。我也试着打电话给 System.gc();但它并没有清除这些东西。

2 小时后看起来像这样

大约 5 小时后内存不足

这些是我的 JVM 参数

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

我将不胜感激。非常感谢。

对于 MySQL 的内容,我使用的是来自此处的 API:SpiderMySQL 和 javax.json.Json; javax.json.JsonObjectBuilder;

我想我找到了问题所在。它是 mysql 库! 看看这里的 class:https://gitlab.com/Syranda/SpiderMySQL/blob/development/src/main/java/de/syranda/spidermysql/WatchThread.java

它不是线程安全的,因为 ArrayList 不是线程安全的。他们已经有一个错误票。

结合这个 class: https://gitlab.com/Syranda/SpiderMySQL/blob/development/src/main/java/de/syranda/spidermysql/table/InsertQuery.java

它让构造函数中的 this 引用转义。这在多线程环境中是非常邪恶的。它会产生奇怪的行为,并且可能会导致内存泄漏。

在这种情况下,您可以尝试切换到纯 jdbc,以测试内存泄漏是否仍然存在。我建议使用任何其他库,它似乎没有很好地实现。

我测试了 JSON 实现,没有内存泄漏