来看懂 游戏《Minecraft》的崩溃报告吧! 服务端/客户端

如何看懂Minecraft报错的关键信息。

 

 

前言

[WARNING] 本篇适用于Minecraft服务端/客户端报错的诊断分析,其他游戏除外,比如网易
[WARNING] 本篇适用于Minecraft服务端/客户端报错的诊断分析,其他游戏除外,比如网易
[WARNING] 本篇适用于Minecraft服务端/客户端报错的诊断分析,其他游戏除外,比如网易

我所说的报错,指的是一款名为《Minecraft》的游戏中的报错。并不是《我的世界》的报错
在大家游玩Minecraft时,有时需要装一些Forge模组以此来提高可玩度,但自己配置模组包的时候,总会造成游戏崩溃,并且大多数人还看不懂崩溃报告更有甚者连崩溃报告输出目录都不知道在哪,于是本篇教程应运而生。

一些俏皮话

Minecraft这个游戏,各种BUG和解决方案如果写成一堆不重复的书,摞起来的厚度可以比姚明还高。
所以这个游戏不是一般的神奇,尤其是当你在看崩溃报告的时,你更会体验到这一点。

你不加模组,MC也会崩溃,加了还是崩溃。这是一个比较罕见的情况。
大多数情况是你一股脑加了一堆模组,然后突然蹦了,就不知道怎么办了。
幸运的是,这时候,你有60%的概率可以找到问题所在并解决这个问题。

寻找崩溃日志

首先,你得知道你的客户端/服务端目录

客户端的CrashReport文件夹目录:(.minecraft\crash-reports)
如果你启用了版本隔离,那就在(.minecraft\versions\xxxx\crash-reports)

服务端的CrashReport在你的服务端根目录下。
这个条件的前提是你的服务端是人类已知的服务端,而不是外星人制造的服务端。

打开崩溃日志

接下来我们对报错的分析,均以一个Minecraft 1.12.2 Forge服务端为例

crashreport文件夹
嗯,我们可以看到,crashreport目录下的所有文件都是以
crash-日期_具体时间-server.txt命名的
如果是客户端的崩溃报告日志,后面的server则是client。

然后我们找到一个最新的日志打开并分析。

告诉你怎么瞬间找到最新崩溃日志,在这里插入图片描述
直接点击这个按钮就完事了。然后会按照报告的生成时间进行排列。

重要的事说三遍

接下来我们对报错的分析,均以一个Minecraft 1.12.2 Forge服务端为例
接下来我们对报错的分析,均以一个Minecraft 1.12.2 Forge服务端为例
接下来我们对报错的分析,均以一个Minecraft 1.12.2 Forge服务端为例

下载文本编辑器

首先你需要一个文本编辑器来查看崩溃报告,
这里我推荐微软官方的Visaul Code: 点我下载.

然后我们就可以愉快地打开报告进行查看了。

开始分析

好了,我们说了这么多废话,是时候开始正式的分析了。
我估计前面的事大多数人已经做完了,就等着我讲这个。

废话不多说,开始。

打开后我们首先看到的是这个
在这里插入图片描述其中,WARNING coremods are present:xxxxx 是废话,你根本不用管。
产生这种警告是因为有的作者动了Minecraft底层的代码,然后Forge为了方便,给你整出来了。
在99.9999999%的情况下,coremods在理论上不会造成崩溃。所以你可以忽略这些。

再往下看。

在这里插入图片描述我们先引出几个重要概念,当然你不用理解。
你会发现这些报错里都会有一大堆的文字:

at net.xxxxx
at org.xxxxxxxx
at com.xxxxxx
at java.lang.xxxx

这些有专门的术语,叫做栈帧(stacktrace)。

平时我们运行Minecraft等java应用程序,是在JVM上运行的。
JVM里内存被划分为五大块,分别是:

       1.   CPU寄存器;

       2.   本地方法栈;

       3.   方法区;

       4.   栈内存;

       5.   堆内存。
寄存器部分容量不够存放太多数据,所以运行中的代码方法会存放在内存中一个叫栈内存内,你可以理解为一个方法一个栈帧。假设报错有20个 at xxx.xxx,那就意味着有20个方法被调用过了。
而会出现这么多的栈帧的原因,是因为上一个栈帧爆出异常后并没有相应的异常处理器去捕获,就会接着爆,报错栈帧就会形成套娃式增长,所以往往最的栈帧就是最后爆出异常的。越往上,这些方法存在问题的可能性也就越大。

我们可以看见,顶上有
在这里插入图片描述
这3行东西,
第一行是废话,你可以不用管。
第二行这个报告中最后一个栈帧抛出异常的时间。
第三行是这个报错的描述,也就是人类可读的大白话形式。
从这开始,下面的句子都不是人类可读形式,当然。相比原版的报错来说,Forge的报错非常非常人性化了。

我们可以从第三行看到,这个崩溃报告的描述是 Ticking player。
player代表球员 玩家,也就是说这个报错跟玩家有关系。
Tciking指的是刻,这个以后再说。

然后我们再来看下面的报错

在这里插入图片描述这个报错片段中。
第一行是错误类型
我们可以看到,这个报错的错误类型是
java.lang.IndexOutOfBoundsException
如果你开过Minecraft群组服务器,或者学过java。你可以知道
这个叫做数组下标越界异常,是一个在Minecraft中非常常见的异常。

我们不用去管这个具体是什么,直接往下看。
下面那些一大堆栈帧的排列,并非没有顺序。
这些栈帧的排列方式,是由它们抛出异常的顺序决定的。
听不懂?我们看图

在这里插入图片描述红色箭头指的栈帧,是第一个抛出异常的栈帧。
然后黄色箭头的栈帧,是最后一个抛出异常的栈帧。
现在你懂了栈帧的排列顺序了吧。
最前面的栈帧就是最后一个抛出错误的位置,也就是说大多数情况我们是从这里下手。
或者从第一个栈帧的后面几个栈帧下手。

 

 

好,我们继续看。

现在我们遇到的是指数组下标越界异常。
例如:一个ArrayList数组中没有元素,而你想获取第一个元素,运行是就会报此类型的错误。
听不懂?我们看报错!

在这里插入图片描述
看看,最后栈帧抛出的异常,就是ArrayList在获取元素的时候没找到。
当然你不用在意这个,继续往下看。

在这里插入图片描述这里已经出现了产生这个崩溃的模组名字。
这个模组叫做:slashblade,也就是大家经常玩的拔刀剑。

然后你发现,这些栈帧的形式都是
at xxx.xxxxxxx.xxxxxx.xxxxxxxx.xxxxxxx.xxxxxx(xxxx.java:xxxx)
如果你以压缩包形式打开拔刀剑模组JAR文件,
你会发现一件事。
那就是这些栈帧其实就是这个JAR压缩包的内部目录结构!!!!!

就比如这条栈帧
at mods.flammpfeil.slashblade.item.ItemSlashBlade$ComboSequence.get(ItemSlashBlade.java:310)

我们可以把所有的" . “去掉,改成” / 或者 \ "
这样就是一个文件目录了!!

at mods.flammpfeil.slashblade.item.ItemSlashBlade$ComboSequence.get(ItemSlashBlade.java:310)
相当于
at mods\flammpfeil\slashblade\item\itemSlashBlade
在这里插入图片描述而这段蓝色的,ComboSequence.get,指的是这个栈帧中抛出异常的方法。并不是文件目录。
括号里的ItemSlashBlade.java:310指的是,
这个异常发生在
ItemSlashBlade.java这个文件夹中的第310行。

是不是突然明白一大堆东西!!!!!!!!!

下面的图就是我用压缩包形式打开拔刀剑模组文件后,
把栈帧转换成目录,就找到了抛出异常的文件路径。

在这里插入图片描述

深度分析

好了,那么我们接下来进行硬核(Hardcore)分析吧

上面我们已经找到了这个崩溃中有拔刀剑的信息
那么我们就进一步分析。

我们知道,拔刀剑有几个栈帧抛出了异常,那么我们以最后一个抛出异常的栈帧进行分析。
amods.flammpfeil.slashblade.item.ItemSlashBlade$ComboSequence.get
从这段信息中我们得知,这个抛出异常的方法在ComboSequence.Get中

ComboSequence翻译过来就是组合技,然后我们进一步分析
既然这个崩溃出在了拔刀剑的组合技上,那也就是说。
我的服务器崩溃是因为,有某个人用了拔刀的组合技,然后不知道触发了什么BUG。服务器就因此崩溃了。

很好,如果你能分析到这一步,那就快接近真相了!

上 代 码

我们首先登陆Github(世界上最大的代码托管站)
然后找到拔刀剑的开源代码仓库,并依次进入目录
src/main/java/mods/flammpfeil/slashblade/item/ItemSlashBlade.java
然后这个就是抛出异常的原代码了。
然后搜索方法 ComboSequence.get

//报错产生的位置
	public static ComboSequence getComboSequence(NBTTagCompound tag){
		return ComboSequence.get(tag.getInt(comboSeqStr));
	}

很好,你可能看见一个熟悉的词汇,叫做NBT
我们引用一段百度百科上的话

二进制命名标签(Name Binary Tag),NBT格式为Minecraft中用于向文件中存储数据的一种存储格式。NBT格式以树形结构并配以许多标签的形式存储数据

既然如此,我们就可以知道
这个报错的产生和NBT标签有关系,然后我们只需要看见tag这个词即可。
这就代表,这个异常的产生是因为在获取组合技的NBT数据时产生异常,在结合最后一个抛出的异常
也就是数组下标越界异常
我们就可以推导出这个异常的产生了。

一个玩家在使用拔刀的组合技时,然后这个组合技因为某种原因无法使用,也就是ArrayList数组元素为空,导致抛出数组下标越界异常,引发Minecraft服务器保护机制然后自动关服。并产生这个报错。

 

以及你会发现栈帧里有一些例如func_xxxxx_x的奇怪方法名。

这些是混淆后的方法名,如果要深究报错产生的话,我们就必须反混淆以便知道具体是什么方法造成了这种问题。

这里我推荐使用MinecraftMappings这个项目

这个项目可以在不用下载很多Forge的情况下方便地生成相应的mapping文件,方便查找混淆后的方法名、字段等的具体含义。

项目的fork地址在: https://github.com/Mohist-Community/MinecraftMappings

这是GitHub的连接,如果你不会用git等工具的话,只需要按下图操作走。

 

 

 

 

 点击Code然后点击Download ZIP

然后你还需要一个IDE,最好用IntelliJ IDEA的community edition(社区版)

 

 

 

 访问https://www.jetbrains.com/idea/download/#section=windows
然后只需要点击Download即可。

IDEA下载后按引导安装。

不要怕看不懂英文和嫌麻烦,因为你都走到这一步了,还有什么理由give up呢?

安装完毕后启动IDEA。

然后刚刚把下载完的源码包解压到一个目录,然后复制源码包解压后的路径并在IDEA里导入新工程(Import Project),路径就粘贴刚刚你复制的源码包解压后路径。

然后IDEA会自动导入这个项目,导入速度和网速有关系,这不需要不管。如果失败那就多试几次或者使用代理加速。

导入完毕后只需要运行main.kt,就可以自动生成mapping文件了,在build目录下。

分别有method、fields、params这3个csv格式的文件。

可以通过wsp或微软office系列软件打开,是表格。

然后直接在里面搜索报错里出现过的对应func、field等字段,就可以看到相关说明了。

有必要还可以下载相关forge源码查询。

 

好了,我们继续看下面的栈帧。
对于下面的栈帧来说,上面的栈帧全是主要原因。也就是说下面的栈帧都是废话
不过我还是贴出来让你了解一下。

在这里插入图片描述很好,接下来我们看红圈内的栈帧。

其中所有 net.minecraftforge.fml.xxxx的栈帧,基本上没什么有价值的信息。
我们继续看下面 net.minecraft.xxxx的栈帧,我们可以看到关键词汇那就是entity

得出结论

Entity就是实体的意思,也就是说这个东西出现在玩家使用组合技与实体进行交互时才发生的数组下标跃境异常

我们继续看
在这里插入图片描述
这2段代表了有关玩家的信息,意义不大。
在这里插入图片描述我们在这些栈帧中可以看到有network和server单词。
这代表这些栈帧与网络和服务端关西了。
这段也是意义不大,而且与拔刀剑产生的报错无关,我们继续看。
在这里插入图片描述
这段才是好戏,我们可以看到一个词组叫playerLoggedOut,这个代表玩家登出服务器。
也就是玩家掉线
然后我们结合这些堆栈抛出异常的顺序。
我们就可以得知一个大概顺序。

  1. 玩家使用组合技后,首先从掉线
  2. 然后服务端发现异常
  3. 然后服务端整理崩溃后就关闭服务器了。
    很好,我们对错误的分析已经结束了。
    接下来我们继续往下看!
  • 完成看崩溃报告的栈帧并得出结论~

修复报错

在这里插入图片描述这是下面的内容。
我们可以看到大大的Head (头部)字样
然后Thread(线程): Server thread(主线程)
我们可以得到一个信息
那就是说,这些栈帧抛出错误是在服务器主线程上抛出的,所以才会导致服务器自我保护机制开启并关闭服务器。

我们继续往下看。
在这里插入图片描述我们可以看见大大的 Player being ticked
这段代表有关出错实体的名字。
然后既然出现了Player,代表这个实体是玩家。
也就代表,这个是出错的实体是玩家。因为那个错误拔刀剑在玩家手上。所以出错实体是玩家。

在这里插入图片描述
然后
Entity Type是实体类型,Entity ID是实体的ID,Name就不用解释了,是实体名。
因为这个实体是玩家,所以实体名就是玩家名。

如果是一只名为蔡徐坤(cxk)的生物(mobs)实体扔出了篮球,造成了异常。那就是
在这里插入图片描述
好了,我们已经知道造成异常的原因、造成异常的玩家了。
那么接下来,就是解决方案拉。

解决方案

好,我们开始解决。
一般来说由实体引起的报错,我们只需要删除这个实体就行了。
这段包含了出错实体,也就是用了错误拔刀剑玩家的位置。
如果这些实体不是玩家,我们可以利用MCEdit、创世神、原版kill指令让这些实体GG。

可问题在于,这个是玩家。那怎么办?

我们有2个办法

第一个是删除有关这个玩家的背包信息,
第二个是打开Forge的错误实体自动移除功能。

我们选择第二个对吧,
我们在服务端的config文件夹内找forge.cfg然后打开
并找到如下两行
然后把false改成true并重启服务器即可。
在这里插入图片描述
好了,报错修复到此结束。

看懂更多

先说一下,这个与解决崩溃没什么关系了
纯粹是为了让你了解更多的东西。
直接上图,
在这里插入图片描述我们可以看到。
System Details的意思是 系统细节
然后下面有
Minecraft Version 游戏版本
Operating System 操作系统型号
Java Version Java版本
Java VM Version JVM版本
Memory 内存大小
JVM Flags JVM附加参数等东西
然后还有Plugins 里面有你加载到服务器里的插件名字
还有FML 代表Forge版本
State和下面的表,是你载入到服务器里的模组和模组的情况
这些英文自己翻译就行了。
建议平时多积累点词汇量。

结束

好了,本文到此结束。转载须注明作者名字和原文地址
本文由Dinnerbone晚餐骨于CSDN上原创发布。

如对你有帮助,或是让你了解了更多知识,那真是再好不过了。

在这里插入图片描述

 

posted @ 2019-12-15 17:12  田所浩托TrosuoTro  阅读(21797)  评论(11编辑  收藏  举报