Java AnnotationProcessor 和 Kotlin Kapt 编译期调试代码——实践与原理

前言

Java 的注解处理器AnnotationProcessor 和 Kotlin的注解处理器 Kapt 会在编译期,根据代码的注解,生成代码。对处理注解的代码进行调试,可以更快的定位问题。那么就需要在编译期调试代码

网上很多文章,只是介绍了如何操作,但是没有说明原理的,导致不明所以,操作时候出现问题就不知从何下手

1、首先我们先对调试器进行一些简单的了解,再去介绍 调试注解处理器AnnotationProcessor就会清晰明了,懂了原理,操作基本就是一次学会。

2、Java和Kotlin 对注解的处理,使用的工具不一样。

  • Java 是使用AnnotationProcessor来根据注解来生成代码,
  • Kotlin 是使用Kapt 来根据注解来生成代码,

所以他们debug调试的方法不太一样,后面会详细介绍

一、调试器

1.1、手动attach调试器

平时在使用AS debug APP的时候,调试器会自动attach到app的进程。

其实我们也可以手动把调试器attach到指定app的进程。

1、点击run 运行 项目,非debug

2、点击as中的attach debugger Android process 按钮
在这里插入图片描述
3、选择调试机中,当前项目的进程
在这里插入图片描述

这样就可以对进程调试了,调试过Android 源码的朋友应该对这个很熟悉。

1.2、远程调试

注解处理器AnnotationProcessor,是在编译期执行的,那么如何把调试器attach到编译期间的进程上

答案就是通过远程调试,远程调试可以把调试器attach到任意时期的进程上

二、调试编译期的Java代码

Gradle 是运行在JVM上的,在初始化的时候会加载一些必要的库,所以第一次运行会有些慢。为了避免每次运行都运行慢的问题,Gradle 推出了一个长时间存活的进程——Daemon (关于Gradle Daemon的官方文档)Gradle 调用AnnotationProcessor 是在Daemon 进程

下面以bufferknife为例,来演示如何调试注解处理器AnnotationProcessor

2.1、创建远程调试

点击Run——>Edit configurations,会打开如下图的界面,点击“+”号,选择Remote
在这里插入图片描述

  • 在1填入名称:Annotation,其他的都不用修改

  • Host和Port 不用修改

  • 复制2处的命令,这是远程调试的jvm命令,在其他运行的进程中,配置这条命令。关于这些参数的说明可以参考这篇博文
    在这里插入图片描述

2.2 配置Gradle任务

首先打开AS右边的Gradle小窗口,然后打开butterknife-integration-test->other目录,找到compileDebugJavaWithJavac,右键选择,如下图所示:

在这里插入图片描述

把在上面复制的命令粘贴到下图VM options的位置:

VM options 是配置Daemon 进程的VM 参数,

注意需要把server=n 改为 server=y,如下 这么做是为了保证compileDebugJavaWithJavac运行前会一直等待调试器的连接。

-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005

在这里插入图片描述

为什么要配置上面这两个东西呢?

  1. 因为调试注解处理器是在compile时期执行的,所以要配置compileDebugJavaWithJavac的任务
  2. 添加那条命令是让compileDebugJavaWithJavac任务可以attach到远程调试

这样当该任务执行的时候,就可以进行调试

2.3 开始调试

在开始调试前,注意一定一定要清掉注解处理器生成的文件,在build文件夹里的文件。可以执行clean project来清理。
因为如果注解所在文件不发生任何改变的话,编译时注解处理器只会运行一遍。不清理再次执行,就直接build完成了

2.3.1 首先在代码中设置断点

2.3.2 执行compileDebugJavaWithJavac

在这里插入图片描述

在这里插入图片描述

因为该任务运行在Daemon 进程 中,也对Daemon 进程配置了远程调试,所以执行该任务(它是个调试任务),会等待远程调试器,所以debug远程调试器就可以断点了

2.3.2 执行远程调试器

选择已创建好的Remote调试——Annotation,启动调试
在这里插入图片描述
这时compileDebugJavaWithJavac,附加到远程调试器,开始正常执行,就会在代码指定断点处停下来

在这里插入图片描述

注意:之前提到过,AnnotationProcessor生成文件一次后,如果注解没有发生改变,接不会再次执行。所以再次调试的时候一定记得clean project

网上有一些是通过命令来实现这个功能,原理是一样的

三、在编译期调试Kotlin代码

在开始介绍方法前,先把原理梳理一下,那么后面操作就会一目了然

Kotlin代码处理注解,使用的是Kapt,而不是AnnotationProcessor

在使用Gradle构建工具,对kapt的处理,不是在Daemon 进程,而是在kotlin.daemon 进程中,所以需要对kotlin.daemon 的jvm参数进行配置,而不能像上面那样配置

3.1 、创建远程调试

和 2.1、创建远程调试 的方法一模一样

3.2 、配置kotlin.daemon 进程JVM参数

gradlew --no-daemon :app:clean :app:compileDebugKotlin -Dkotlin.daemon.jvm.options="-Xdebug,-Xrunjdwp:transport=dt_socket\,address=5005\,server=y\,suspend=n"

–no-daemon 不使用daemon进程
-Dkotlin.daemon.jvm.options 对kotlin.daemon进程设置远程调试参数

命令中的\ ,千万不要去掉,否则调试不了

3.3、执行远程调试器

kotlin和java 不太一样,java 会等待远程调试,而kotlin需要一定的手速

执行3.2的命令后,会依次执行gradle 的任务,在执行到下面的任务的时候,立即启动远程调试器,启动方式2.3.2 节一样

:app:kaptGenerateStubsDebugKotlin

这个任务会停留3秒的左右时间,来让你启动远程调试,一般一次就可以启动成功

成功断点是这样子的
在这里插入图片描述

这里延伸 一下,kapt是先生成stub (一个java类),然后根据生成的java类的注解,去生成代码 ,如下图
在这里插入图片描述

参考:

如何调试编译时注解处理器AnnotationProcessor
编译时注解处理方
Annotation Processor
调试Annotation Processor编译时注解器
如何debug自定义AbstractProcessor
Android APT 编译期进入debug模式

Annotation Processing with Kapt and Gradle
Debug Annotation Processor Kapt
Can’t Debug an Annotation Processor when using kapt and gradle
Android Studio中kapt调试annotation processor的一些注意事项

发布了242 篇原创文章 · 获赞 775 · 访问量 224万+

猜你喜欢

转载自blog.csdn.net/xx326664162/article/details/91456018
今日推荐