开篇
学习源码第一步就是搭建调试环境,但是看了网上大部分 Elasticsearch 调试方式都是配置各种环境变量然后直接启动 Main 方法,而且还各种报错。今天提供新的方式--remote debug 来避免这些麻烦。
步骤
环境
首先要安装 jdk8,gradle 和 Intellij IDEA
源码下载
拉取代码,checkout 到想要调试的版本 (这里切到 v6.1.0,需要注意的是不同 ES 分支对 gradle 版本要求不一样,可以到 README 文件中查看对应到 gradle 版本要求)
git clone git@github.com/elastic/elasticsearch
cd elasticsearch
git checkout v6.1.0
导入到 IDEA
执行 gradle idea, 成功后会提示 BUILD SUCCESSFUL,然后导入到 IDEA
:test:fixtures:hdfs-fixture:idea
:test:fixtures:krb5kdc-fixture:ideaModule
:test:fixtures:krb5kdc-fixture:idea
:test:fixtures:old-elasticsearch:ideaModule
:test:fixtures:old-elasticsearch:idea
BUILD SUCCESSFUL
Total time: 2 mins 2.159 secs
使用 gradle 启动 Elasticsearch
gradle run –debug-jvm
执行成功后是这样的,其中 8000 就是远程 debug 端口
配置 remote debug
点击 IDEA 的 Edit Configurations,再点击➕填写主机和端口,Name 是配置名称,可以自定义(我这里就填 es),点 OK 保存配置搜一下源码里面 Elasticsearch 类,,看到 Main 方法,先打个断点等会看效果最后再点下绿色小虫子启动 debug 是不是在断点停下来了跳过断点再看下控制台,是不是启动日志都出来了再验证下是否启动成功
原理
一切源于被称作 Agent 的东西。JVM 有一种特性,可以允许外部的库(Java 或 C ++ 写的 libraries)在运行时注入到 JVM 中。这些外部的库就称作 Agents, 他们有能力修改运行中 .class 文件的内容。这些 Agents 拥有的这些 JVM 的功能权限,是在 JVM 内运行的 Java Code 所无法获取的,他们能用来做一些有趣的事情,比如修改运行中的源码,性能分析等。像 JRebel 工具就是用了这些功能达到魔术般的效果。传递一个 Agent Lib 给 JVM, 通过添加 agentlib:libname[=options] 格式的启动参数即可办到。像上面的远程调试我们用的就是 -agentlib:jdwp=… 来引入 jdwp 这个 Agent 的。jdwp 是一个 JVM 特定的 JDWP(Java Debug Wire Protocol)可选实现,用来定义调试者与运行 JVM 之间的通讯,它的是通过 JVM 本地库的 jdwp.so 或者 jdwp.dll 支持实现的。简单来说,jdwp agent 会建立运行应用的 JVM 和调试者(本地或者远程)之间的桥梁。既然他是一个 Agent Library, 它就有能力拦截运行的代码。在 JVM 架构里,debugging 功能在 JVM 本身的内部是找不到的,它是一种抽象到外部工具的方式(也称作调试者 debugger)。这些调试工具或者运行在 JVM 的本地 或者在远程。这是一种解耦,模块化的架构。
关于 Agent 还有很多值得研究的细节,甚至基于 JVMTI 自己实现。参考 https://www.ibm.com/developerworks/cn/java/j-lo-jpda2/index.html