受到委托,我将对一个 70~80人 的MC服务器检查卡死原因的任务。
连接后台后,第一时间我查看了服务端核心,服务器核心使用的是 arclight-fabric 1.21.1。
然后我查看了任务管理器:

任务管理器显示,内存占用比较高,但CPU占用并不高,所以首先排除是 GC 导致的JVM暂停。
回到服务端控制台,输入命令发现并没有反馈。
所以我拷贝了一份 arthas调试工具 到目标服务器上,并注入到目标服务端。
随后我输入了线程命令,来查看所有线程的状态:

发现并没有发现服务端的主线程(Server Thread),线程也都没有占用。
所以我携带了查看所有线程的命令(thread -all),在里面找到了主线程:

发现主线程是 WAITTING状态,这代表主线程正在等待一些任务执行完成。
所以我就使用命令查看了一下主线程的堆栈(thread 150):

这里可以看到,他是在等待一个叫做 CustomChunkLimits 的一个插件里面的一个任务处理:

所以我们使用 dump命令 将目标类提取出来:

提取出来后,我们丢到反编译工具中分析这个类和对应 71行的代码:

发现这里有一个 for语句和一些配置读取操作,所以我们结合配置文件内容计算这个for总共要处理多少次:

可以看到 CheckChunk 为 2,而 Min 为 0,Max为 320,所以这一个代码总共要执行 5 x 5 x 16 x16 x 320 次,也就是 2048000 次。
也就是我们不小心将 CheckChunk 设置为了 2,导致插件这个代码执行的次数十分巨大,导致主线程一直在等待任务执行完成。
后续,我们将 CheckChunk 设置为 0,就解决了这个问题。
