java - Java中的WeakHashMap如何泄漏内存?
问题描述
我正在运行一个大型 Minecraft(Spigot) 服务器,它带有一个专有的、严重混淆的 AntiCheat 插件以及我们定制的一组经过实战测试的插件。服务器多次创建和卸载新世界,因此在卸载、离开CraftPlayer
和CraftWorld
对象后进行 GC。
我们正在使用 G1GC 和所谓的“aikar gc flags”在 Java 13(Java 12 也是如此)上运行
java -XX:+UseLargePagesInMetaspace -XX:+UseG1GC
-XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=100
-XX:TargetSurvivorRatio=90 -XX:G1NewSizePercent=50
-XX:G1MaxNewSizePercent=80 -XX:G1MixedGCLiveThresholdPercent=35
-XX:+ParallelRefProcEnabled -jar Spigot.jar
AntiCheat 保持对CraftPlayer
s 的弱引用,但它们会泄漏,并且由于泄漏足够大,服务器的 CPU 会非常剧烈地旋转以最终与OutOfMemoryError
. 手动运行System.gc()
也不会清理这些。
当 AntiCheat 被禁用时,泄漏就消失了。
CraftWorlds
堆转储中对所有泄漏的唯一 gc-root 引用CraftPlayer
是 中的条目WeakHashMap
,键是CraftPlayer
。(CraftPlayer
并CraftWorld
在正常 GCd 之前相互交叉引用)。
有一种方法可以通过 a 进行泄漏WeakHashMap
:如果您没有积极使用触发expungeStaleEntries()
. Map<String, WeakHashMap<...>>
如果AntiCheat 使用类似WeakHashMap
.
还有一个问题:在这种泄漏中,您可以看到WeakHashMap
' 的队列将是非空的!然而它是空的,正如我检查的那样!我也注意到WeakHashMap
被包裹synchronizedMap
,但在我看来这可能不是问题。
这真的是由其中一个标志引起的 GC 错误吗?
这种模式每次都在每个堆转储中重复:
解决方案
推荐阅读
- html - 点击事件后如何在ionic 4中的iframe中获取加载页面的内容
- c - 使用此功能复制 2d 图像数据 - 为什么有效?
- powershell - 导出具有不同数据的 CSV
- ssl - 带有 seflsigned ssl 证书的本地 Gitlab 服务器
- bash - 我想按升序显示 Name1 到 Name15 但不只是回显每个
- sql-server - 将查询运行的实际执行计划保存为 SSIS 包的一部分
- postgresql - 在 psql 的一列中连接日期(时间戳)和小时(数字)列
- android - ExpandableListView - 更新或删除特定行而不调用 Activity 中的适配器
- sql - 已经插入的数据替换到另一个 UserId
- r - 无法通过 googleAnalyticsR 导出超过 1000 行