本帖最后由 754503921 于 2019-7-2 08:36 编辑

如何从一万个报错排查到清零
—— 报错大全与解决方案
开服的时候,各位腐竹一定遇到过这些信息,也就是所谓的报错。
这篇帖子将会教你怎么看报错,找问题,并且不需要Java基础。
这里的看不懂也没关系,可以往下翻到常见异常大全。

一个典型报错的格式

分为两种,第一种
这种报错分为几个部分
  • 一个可能的 Error occurred while xxxxxxxxx
  • 一个报错种类,如上红色部分
  • 报错种类后跟随的可能的报错原因,如上橙色部分
第二种如下
此类报错分为以下部分
  • 一个可能的 Error occured during xxxxxx 提示你报错了
  • 一个报错类型以及随后的可能有的报错原因,如上 java.lang.Throwable
  • 一个或多个详细报错信息,格式为 Caused by: 报错种类: 报错原因
两种报错都有如下格式,分别是:
  • (Caused by:) java.xxx.XxxException: some reason,我们称之为异常类型
  • (Caused by:) java.xxx.XxxException: some reason,我们称之为异常信息
  • at xxx.某些插件的.包名.xxx.发生错误的类名.错误的方法名(类名.java:行数) ~[资源地址:版本],我们称之为栈信息
  • ... X more,我们称之为省略的栈信息
  • 另外在Bukkit里,一般会有提示信息,如上紫色,我们称之为Bukkit信息
  • 部分插件作者会提供报错前的一段说明,我们称之为插件信息
请牢记上面的5个名词,在接下来的内容,我将频繁使用这五个词。

判断这个报错发生的原因

我想从我的端翻几个报错结果发现一个没有,那就只好去联机问答找一个来
结果发现联机问答没有啥适合讲的报错
示例一
  • 先看Bukkit提示信息,中文意思为 无法加载文件夹 'plugins' 中的 'plugins\DynmapPlotMe.jar'
  • 接着看异常类型,我们一般看最后的类名,如上红色部分的 UnknownDependencyException,意味未知依赖异常
  • 接着看异常信息,dynmap
分析得出,这个报错由于 DynmapPlotMe.jar 插件需要依赖 Dynmap 插件,而 Dynmap 未安装,于是报错。
必要情况下我们需要查看栈信息来判断错误原因。
示例二
  • 先看Bukkit提示信息,意为 AuthMe v3.5-SNAPSHOT 处理 PlayerJoinEvent 事件时报错
  • 接着看异常类型,看最后的大驼峰类名,为 EventException,事件异常
  • 接着看下一个异常类型,NullPointerException,空指针异常
由于空指针异常(常称为 NPE)是最难以判断错误的异常,所以我们需要看情况查看栈信息
经验:查看栈信息时,常从第二个异常类型(Caused by: java.lang.NullPointerException)下方的栈信息开始,多为 Caused by 开头
  • at net.milkbowl.vault.permission.plugins .Permission_GroupManager.getPrimaryGroup(Permission_GroupManager.java:327) 中有 Permission 字样,说明可能是权限带来的报错,资源地址为 Permission_GroupManager.java,说明可能是 GroupManager 插件带来的报错
  • at fr.xephi.authme.listener.AuthMePlayerListener.onPlayerJoin(AuthMePlayerListener.java:726) ~[?:?] 中,包名为 authme,调用方法 onPlayerJoin,说明可能是玩家加入时进行的权限检查的错误
事实上确实是 GroupManager 的设置失败带来的报错,紧跟着这条报错的后一条也证明了这一点:(Residence 也查询了权限)

解决一个异常
接着上面的报错来说,我们已经判断了是 GroupManager 的报错,那么怎么解决呢?(前提是 GroupManager 支持你的版本)
我们应该在茫茫似海的报错群中寻找 GroupManager 的报错信息,如下:
  • GroupManager 是个仔细写的插件,所以提供了插件信息:其中有一句 The following file couldn't pass on Parser. plugins\GroupManager\worlds\world\groups.yml,说明是 GroupManager\worlds\world\groups.yml 配置文件出了一点小差错
  • 接着看Bukkit信息,意为 启动 GroupManager v2.0 (2.12.1) (Phoenix) 时出现异常
  • 接着看异常种类和异常信息,异常种类不认识没关系,异常信息与插件信息相同
  • 接着看下一个异常种类,与上一个基本相同
  • 接着看下一个异常种类和异常信息,Caused by: org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1,含有 charset 字样,意为 编码,说明这个配置文件可能编码有误
  • 接着看下一个,Caused by: java.nio.charset.MalformedInputException: Input length = 1,看不懂,不过没关系,我们已经解决了问题
经过分析,GroupManager 的组文件的编码有误,因为示例服务端为 1.8.0,所以应转码为 ANSI
类似的解决方法还有
  • 删除报错插件
  • 删除报错配置文件或编辑至正确
  • 按照报错的异常信息自行操作
  • 将异常信息提交给作者

常见异常类型列表及解决方法
善用 Ctrl+F 搜索
服务器启动
InvalidDescriptionException: Invalid plugin.yml

UnknownDependencyException: xxxx

IllegalArgumentException: The following file couldn't pass on Parser.

CommunicationsException: Communications link failure

ReaderException: special characters are not allowed
InvalidConfigurationException: unacceptable character

InvalidConfigurationException: while scanning an anchor
InvalidConfigurationException: while scanning a simple key

InvalidConfigurationException: mapping values are not allowed here

InvalidConfigurationException: while scanning for the next token

NoClassDefFoundError: aa/bbbb/CcccDdddd

SocketTimeoutException: connect timed out
SocketTimeoutException: Read timed out
SocketException: Connection reset
SocketException: Software caused connection abort: recv failed
ConnectException: Connection refused: connect
ConnectException: Connection timed out: connect

UnsupportedClassVersionError: xx/xx/Xxxxx : Unsupported major.minor version XX.0

SQLException: file is encrypted or is not a database

RuntimeException: Essentials API is called before Essentials is loaded.

InvalidConfigurationException: while parsing a block mapping

FileNotFoundException: plugins\XxxxXxxx\yyy.yml (拒绝访问。)


服务器运行时

UnhandledException: Plugin Xxxxxxx vX.0 generated an exception while executing task x

IllegalArgumentException: Async entity add

ClassCastException: xxx.xxx.XxxXxx cannot be cast to yyy.yyy.YyyYyy

ClassNotFoundException: net/minecraft/server/v1_X_RX/XxxxXxxx

OutOfMemoryError: Java heap space

NoSuchFieldError: XXX_XXX
IllegalArgumentException: No enum constant xxxxx.xxx.XX_XXX
NoSuchMethodError: xxx.xxx.XxxXxx.xxXxx

IllegalArgumentException: Entry cannot be longer than 16 characters!

ArrayIndexOutOfBoundsException: X

CommandException: Unhandled exception executing command 'xx' in plugin XxxXxx vX.Y

FieldAccessException: No field with type xxx.XXX exists in class YyyyZzzz.

NumberFormatException: For input string: "XXX"

IllegalStateException
StackOverflowError
ConcurrentModificationException

Caused by: <eval>
ScriptException: TypeError: XXXXX

AuthenticationUnavailableException: Cannot contact authentication server


其他

EventException

NullPointerException

UnknownHostException: xxx.website.com

[Server thread/ERROR]: Ambiguous plugin name `Xxxxxx' for files `plugins/Xxxxxx1.jar' and `plugins/Xxxxxx2.jar' in `plugins'

Unable to instantiate org.fusesource.jansi.WindowsAnsiOutputStream

MissingResourceException: Can't find resource for bundle java.util.PropertyResourceBundle, key org.bukkit.xxxxxx

如何从栈信息诊断
栈信息主要从以下几点判断
  • 格式
  • 关键字

格式

关键字(解决 NullPointerException)
常用于普通方法无法分析的情况。

示例一
栈信息从上往下看。
me.**.GameManager.loadTiles(G***4) ~[?:?],由于含有 GameManager 字样,结合这个插件是由同一个作者使用同一个前置开发的,所以可能是前置库的版本过低。

示例二
栈信息的第 2 - 5 条都含有 configuration 字样,所以是配置文件的问题。
第 6 -7 条为 rpgitem 插件的包名,并且含有 ItemManager(物品管理器)字样,
所以是RPGItem插件的物品保存配置文件损坏。

示例三
这份报错为 Residence 插件的报错,分析栈信息,发现有 teleport 字样,所以可能是传送出现的问题。
所以可能是领地插件的保存文件损坏,导致领地的传送点获取失败(getTeleportLocation)。

看懂 Spigot Watchdog 报告
什么是 Spigot Watchdog
Spigot Watchdog 为 spigot 内置的用于检测服务器状况的模块,当服务器卡死后,Watchdog 将会强制停止服务器并打印所有线程的信息。
所以一般Watchdog报告都特别长。

一份典型的 Watchdog 报告

为了不使整个报告过长,我使用 *** 对部分进行了省略。
当你查看日志文件时,Watchdog 的报告有以下几点典型的特点:
  • [Spigot Watchdog Thread/ERROR]
  • The server has stopped responding!
  • Please report this to http://www.spigotmc.org/
  • Be sure to include ALL relevant console errors and Minecraft crash reports
  • Server thread dump (Look for plugins here before reporting to Spigot!):
当你确定好这是Watchdog的日志后,你需要找出问题所在。

找到导致卡顿的线程

很简单,直接在日志文件中搜索 State: BLOCKED 即可
如上,导致卡顿的线程的栈信息就被找了出来
红色部分为阻塞标志,紫色部分为对应插件的信息。
由此可以看出,是使用 ProtocolLib(包名为com.comphenix.protocol)的插件进行网络操作(io.netty包)导致的卡顿。

一些其他的诊断方法

我们可以通过搜索 Server thread 来查看服务器主线程的卡顿情况,如下
这两个栈信息都是Server thread的信息,可以看到阻塞在了 ServerConnection(服务器连接) 和 com.mojang.authlib.GameProfile.toString(mojang的登陆验证),那么可能是玩家连接服务器时连接又断开了,导致服务器卡顿。

欢迎各位腐竹到这里提问咨询报错信息,如果实用我会将其添加进入。
当然如果你知道某些报错以及解决方法也可以回复。
在找报错之前请先确认你使用的插件版本是否严格符合服务端版本
报错了有时最好的解决方法是更新。

[groupid=1330]PluginsCDTribe[/groupid]