调试插件
平时我们很难定位插件里一个 Bug 的具体位置,重新编译并且加一大堆测试代码会让人想上天,因此,本节教程将教会你如何利用 Java 的 Debug 功能.
准备你的工作环境
由于我们将在你的 IDE 中运行 Sponge 和你的插件,所以您需要导入 SpongeForge 或 SpongeVanilla ,具体取决于你要使用哪个。相应项目的 GitHub 页面上提供了如何做的说明。在继续操作之前,请仔细按照这些说明进行操作。
现在,你需要确保您的插件项目对您刚刚创建的 SpongeForge/SpongeVanilla 项目可见。所需的步骤取决于你的 IDE。
IntelliJ IDEA
在 IntelliJ 中,每一个项目都有它自己的一个工作环境。所以如果你想要让你的项目对 Sponge(Vanilla) 可见,你需要将其作为一个 Module 。假设你已经按照 设置 IntelliJ IDEA 描述的方式创建了你自己的项目,那么请按下面的步骤做。
打开
SpongeVanilla
/SpongeForge
项目。单击
File
,然后单击New
,然后单击Module from Existing Sources...
。定位至你的插件的根目录。
如果你正在使用 Gradle,请选择
build.gradle
文件,然后在下一步选择Use auto-import
并点击确定。否则请直接选择整个目录并点击
Finish
。
点击
Finish
。
小技巧
如果你还没有创建你自己的插件,请单击 Module...
而不是 Module from Existing Sources...
,并按照接下来的指示新建项目。
Eclipse
只需要直接按照 设置 Eclipse 中描述的方式创建项目。只要它和 SpongeVanilla
/SpongeForge
在同一个工作区,那么你的插件项目就对它们可见。
将插件添加到 Sponge 的 CLASSPATH 中
这背后的想法是,我们将从你的 IDE 中像正常项目一样启动 Sponge,但区别在于我们将把你的插件添加到 CLASSPATH 中。由于 Sponge 将默认加载在 CLASSPATH 中找到的所有插件,将插件项目添加到 Sponge 的 CLASSPATH 中将会使你无需在每次更改后重建并将项目文件复制到你的 Sponge 服务器目录下。
首先你需要确认你的运行和调试配置都已设置好。请根据 Sponge 的 README.md 中的内容进行检查。
然后你需要编辑你的运行和调试配置使得你的工作目录已被加入到 CLASSPATH 中。请再次根据你的 IDE 进行这一操作:
IntelliJ IDEA
打开你的项目的 Project Structure。
单击
File
,然后单击Project Structure...
。或者直接点击
Project Structure
按钮,该按钮位于你的 IDE 的右上角,Search
按钮的旁边。
单击
Modules
并展开SpongeForge
或SpongeVanilla
组(取决于你选择了什么)。确定你已选择了
SpongeForge_main
或SpongeVanilla_main
中的一个。在右侧列中选择
Dependencies
选项卡。点击底侧的
+
(添加)按钮,然后选择Module Dependency
。选择你的插件项目(
yourplugin_main
)在添加后 不要 检查
Export
选项。
警告
因为 Intellij IDEA 的一个 Bug(IDEA-194641),你的插件的所有依赖(比如 Kotlin 标准库、GSON 等)不能通过上述方式添加到你的 classpath 中。这会导致你的插件虽然能成功编译,但在调试中访问这些类时抛出 ClassNotFoundException
。
这个问题只会影响你在 Intellij IDEA 中以一个模块的形式运行你的插件。你最终构建出的插件仍然可以在 Intellij IDEA 和生产服务器上正常工作。
如果你的插件有外部依赖,你需要按以下步骤操作以能在 Intellij IDEA 中正常运行你的插件:
新建新的 Java 模块。依次点击
File
->New
->Module...
,命名为SpongeForgeContainer
。打开之前新建的
SpongeForgeContainer
的模块设定。在
SpongeForgeContainer
的依赖选项中,添加对SpongeForge_main
的模块依赖。编辑服务器的启动配置。将
Use classpath of module:
从SpongeForge_main
改为SpongeForgeContainer
。
其他选项保持不变。现在,你的插件所有的依赖都应该能正常添加到服务器的启动 classpath 中了。
Eclipse
找到你的运行或调试配置
单击
Run
,然后单击Run Configurations...
或者,请分别点击 Run/Debug 图标对应的下拉菜单后的
Run Configurations...
或Debug Configurations...
。
在左侧栏选择关于 Sponge(服务端)的运行或调试配置。
切换到
Classpath
选项卡。选择
User Entries
,然后单击Add Projects...
按钮。选择你的插件项目。
单击确定按钮。
单击右下角的应用按钮。
运行你的配置
在你执行了上面的操作步骤后,你就可以开始调试你的插件了。如果你从你的 IDE 启动你的服务器,那么它的运行目录应为你的 SpongeForge/SpongeVanilla 下的 run
目录。所有服务端创建的文件(包括世界、配置等)都将存储于该目录并且每次都将从该目录启动服务器,就像你手动将服务端的 JAR 复制到了该目录下并启动一样。
IntelliJ IDEA
如果你想要调试,请不要点击表示运行或调试的两个按钮的绿色小箭头,而应点击旁边的绿色 Debug
按钮。
Eclipse
如果你想要调试,请不要点击表示运行或调试的两个按钮的绿色小箭头,而应点击 Debug 按钮旁边的下拉小箭头(因为一个 BUG)弹出一个下拉菜单,然后再点击 Test (Server)
配置。如果它并不存在在下拉菜单中,请点击 Debug Configurations
,然后点击 Test (Server)
配置并点击右下角的 Debug
按钮。
使用调试器
现在你的服务端(和你的插件)都在以调试器的方式运行了。你可以开始利用调试器的种种特性。下面简要介绍最明显的用法,尽管它们不属于 Sponge,而属于 IDE 使用的 Java Debugger 的特性。
断点
若要仔细看看代码,断点是一个很有用的工具。断点可以在代码行或方法的开头设置。当到达断点时,调试器将停止代码执行,同时 IDE 将打开一个视图,允许您检查当前范围中所有变量的内容。代码执行将不会还原,除非您在 IDE 的调试视图中按相应的按钮。
在调试的过程中,你可以任意地添加、移除、或者临时禁用断点。
小技巧
一旦单个服务器检查需要超过给定的时间,监视器(Watchdog)将会认为服务器崩溃并强制关闭它。当使用断点时这件事就可能会发生了,因此建议您编辑测试环境的 server.properties
文件,并将``max-tick-time`` (毫秒)的值设置为一个非常大的数字,或干脆直接设置为 -1
(完全禁用监视器)。
IntelliJ IDEA
若要添加或移除断点,只需在你的 IDE 的文本编辑器界面左侧的空白区域左键单击。
或者,将光标放在要添加或删除断点的行中,然后单击 Run
并单击 Toggle Line Breakpoint
。
Eclipse
若要添加或移除断点,只需在你的 IDE 的文本编辑器界面左侧的空白区域右键单击并点击 Toggle Breakpoint
。
或者,将光标放在要添加或删除断点的行中,然后单击 Run
并单击 Toggle Breakpoint
。
代码热替换
调试器的另一个主要特点是,你不必为每一个小的变化重新启动服务器,因为我们可以进行代码热替换。这意味着您可以在调试器中运行代码时重新编译部分代码。当然,这有几个限制,其中最重要的是:
你不能添加或移除方法。
对方法的改变仅限于方法 内 的代码。也就是你甚至连方法的签名(Signature)都不可以改变(这包括方法名称、返回值以及参数类型)。
你不能移除一个类。
你不能修改一个类的名称、父类、以及它实现的接口列表。
你可以添加类。不过,它一旦添加并通过代码热替换的方式进行加载,你就不能对这个类做上面提到的操作了。
你可以测试这个功能:在插件中引入一个简单的命令,而且该命令的作用只是输出一个词,比如 Sponge
,然后保存并启动服务器,如上所述。运行命令。它会输出 Sponge
。现在改变命令,使其输出一个不同的词到控制台,保存文件。更改后,请执行以下操作以将更改传送到正在运行的程序:
IntelliJ IDEA
从 IDE 的顶部打开
Run
菜单。在第一个分组的分隔线后,单击
Reload Changed Classes
。
Eclipse
不需要任何操作。你一旦保存这个文件,它将被重新生成,然后热替换到当前运行的调试器中。除非你改变了这种特定的默认行为,否则你不需要手动触发代码热替换。