Gradle Remote调试

1,084 阅读4分钟

一、背景

Gradle作为当前主流的项目构建工具之一,基于插件基础上可以很方便的实现动态扩展,如基于AGP基础上为Android项目提供了构建能力。项目构建过程中,以Gradle Task为实际上的构建处理单元,依次完成整体上的构建流程。实际项目开发中,无论是基于已有Gradle/AGP的配置,还是自定义Task,甚至是自定义插件,都会被广泛的使用到。这其中,尤其基于自定义插件,可以为项目在构建过程中提供丰富的可扩展能力。

Gralde在配置、自定义Task甚至自定插件过程中,被诟病最多的,其本身欠缺的调试能力必居其中。项目本身其实还好,直接通过如print输出对应信息可以变通的达到调试的目的,但在自定义插件的开发过程中,通过日志输出的方式查找问题往往很不方便,费时费力。

Android Studio,基于IntelliJ IDEA,实际上为我们提供了Remote调试的能力。基于JDWP协议基础上,可以将Debug Process与Remote Process进行关联,使得Remote Process具备debug的能力。当然,这将基于如下两个前提:
1,Remote Process具备并开启基于JDWP协议动态调试的能力;
2,Debug Process正确配置,充当Client或Server角色,与Remote Server简历连接,现实中用的多的是充当Client角色。

Gradle进程在运行过程中,通过参数配置,可以具备上述的基于JDWP协议动态调试的能力。因此,通过与Remote相结合,可以达到我们期望中的对Gralde在构建过程中进行调试的效果。


二、配置与效果

2.1 Gradle开启调试

Gradle本身提供了丰富的命令及可选参数,我们可以通过./gradlew --help看一下:

其中,“-D, --system-prop”使得我们可以设置对应的系统属性,以得到所要的效果。

Gradle提供了丰富的系统属性配置。具体可以参照官方文档: docs.gradle.org/current/use…

其中,有我们需要的org.gradle.debug属性,通过对其设置,可以开启Gralde进程的Remote调试。

这个文档上的其他属性及含义有些场景下也都非常有用,感兴趣可以分别实践下。

2.2 配置步骤

1,Android Studio点击 "Make Project" 右边的 ”Edit Configurations“,调出 ”Run/Debug Configurations“ 界面。
2,点击左上角”+“,新建配置,类型选择 ”Remote“。
3,重命名 ”Name“ 项,如”GradleDebug“,其他项保持默认不变,点击 ”OK“,新建完成。

项目说明
Debug modeAttach to remote JVM:Debug Process作为Client,连接到Remote Process
Listen to remote JVM: Debug Process作为Server,等待Remote Process连接。
默认通常使用”Attach to remote JVM“
HostRemote Server的Host地址,本机使用“localhost”
PortRemote Server的对应的Port,默认”5005“,最好不要修改。
Command line arguments for remote JVM默认 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
jdwp:jdwp协议,对应”Java Debug Wire Protocol“的简写
dt_socket:表示通过socket协议建立连接
Use module classpath选择需要调试的对应项目或模块,默认"<no module>"指的是整个工程,也可以选择自己需要的具体模块

4,Gradle执行Task时开启调试功能。
在原本Gradle执行命令基础上加上参数:Dorg.gradle.debug=true --no-daemon。

5,在需要位置打上断点。

6,构建时选中刚新建的 “GradleDebug”,并点击其右边的 “Debug”。此时进入调试状态,Debug界面会显示对应调试信息,并可以通过通用断点调式方式调式。

2.3 示例及效果

2.3.1 断点调试Gradle Clean
对应命令为:

./gradlew clean -Dorg.gradle.debug=true  --no-daemon

对应输出提示如下:

To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/5.1.1/userguide/gradle_daemon.html.
 
> Starting Daemon

在需要位置打上断点,点击 Debug 后,显示效果:

2.3.2 断点调试自定义Task
自定义Task tt,断点后执行

./gradlew tt  -Dorg.gradle.debug=true  --no-daemon

2.3.3 自定义插件中断点调试
自定义Gradle 插件后,设置断点,执行Task:

./gradlew assembleDebug  -Dorg.gradle.debug=true  --no-daemon

2.3.4 断点注解处理器
是的,注解处理器也是可以断点的,方式都是一样的,在自定义注解处理器中设置断点,执行Task:

./gradlew assembleDebug  -Dorg.gradle.debug=true  --no-daemon


三、停止调试进程

3.1 停止Debug Process

在Debug界面,各操作与通常调试Java程序相同,如果需要停止调试进程,可以通过点击界面左边的 "Stop"按钮。

3.2 停止Gradle Task进程
停止Gradle Task进程有两种方式,分别为:
1,通过快捷键组合方式。推荐使用。
通过 Ctrl + C 快捷键组合,连续多次组合键按下,一般三次就可以当前进程终止。

2,通过命令方式。
通过命令 ./gradlew --status,可以查到当前所有的Gradle进程状态,通过./gradlew stop可以终止当前所有Gradle进程。
也可以通过对应的Linux命令:ps -9 [process_id] 去终止进程。

注:
使用过程中,如果出现如下错误提示:

Remote Configuration debugger **can not be attached.

这是因为端口(默认5005)已经被另一个正在运行的Gradle守护进程占用了,通过./gradlew stop停止进程即可。


四、参考文档

docs.gradle.org/current/use…
www.jetbrains.com/help/mps/ru…
stackify.com/java-remote…