IDEA或Eclipse中编译调试ElasticSearch源码
对于想深入学习ES的人来说,编译源码,从而方便的进行阅读、调试是必不可少的。这方面的文章也不少,我尝试过几个,但多多少少都碰到了一些问题。最后参考官方的一篇博客编译成功了,可以正常的调试代码,且步骤简单。原文也不长,英文能力还行的可以直接阅读原文: How to Debug Elasticsearch Source Code in IntelliJ IDEA
。这里我简单总结并扩展一下,也支持Eclipse,并说明一下实际操作中要注意的细节。
关于JDK版本
ES是Java开发的,所以编译的时候肯定是需要JDK的。但需要注意,ES运行所需的JDK版本和编译所需的JDK版本要求是不一样的。运行ES,一般JDK 1.8(Java 8)就可以了(而且推荐该版本),而且从ES 7.0版本开始,默认下载的安装包里面已经集成了JDK。但是编译ES可不行,我编译ES 6.4版本的时候,需要的JDK版本是10,编译6.6版本的时候,需要的JDK版本已经是11了。所以,编译时所需要的JDK版本取决于你想编译的ES版本,源码根目录的
CONTRIBUTING.md
文件中贡献代码部分一般会指出编译所需的JDK版本(并且还有很多其它有价值的信息,比如如何使用Eclipse或者IDEA进行源码开发、编译、调试,建议看一下)。另外如果JDK版本不对,编译的时候会有错误信息提示。反正编译完之后,我的电脑上面现在已经装了JDK 1.8、JDK 9、JDK 10、JDK 11四个版本了,需要哪个用哪个。
这里以原文中的ES 6.6版本为例进行说明。ES 6.6版本编译依赖于JDK 11(必须),另外有些代码模块依赖于JDK 9,但这部分代码非必须,所以建议也安装好JDK 9,并为其设置环境变量 JAVA9_HOME
,编译时会通过该环境变量找JDK 9. 但JDK 9并非强制,如果你没有,编译的时候也不会报错,只会出几个警告。
最后贴上我的JDK环境变量的配置:
export JAVA8_HOME=$(/usr/libexec/java_home -v 1.8) # 可选。如果是Linux或者Windows,将命令换为JDK的真实路径 export JAVA9_HOME=$(/usr/libexec/java_home -v 9) # 可选 export JAVA10_HOME=$(/usr/libexec/java_home -v 10) # 可选 export JAVA11_HOME=$(/usr/libexec/java_home -v 11) # 必须 export JRE_HOME=$JAVA_HOME/jre export CLASSPATH=.:$CLASSPATH:$JAVA_HOME/lib:$JRE_HOME/lib export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin // 运行的时候使用Java 8(ES会读取该环境变量) export RUNTIME_JAVA_HOME=$JAVA8_HOME # 可选
1, 下载源码(这一步对于网络不好的人会很漫长),然后切换到自己想要的分支,这里使用6.6分支:
git clone https://github.com/elastic/elasticsearch.git cd elasticsearch git checkout --track origin/6.6
2, 生成IDE所需要的文件:
// Eclipse ./gradlew eclipse // IDEA ./gradlew idea
3, 把代码导入到Eclipse或者IDEA中:
// Eclipse File: Import: Existing Projects into Workspace -> 选择ES源码目录 -> Search for nested projects // IDEA File->New Project From Existing Sources -> 选择ES源码目录 -> Import project from external model->Gradle
导入后,会自动开始编译,这又是一个很漫长的过程。这里可以做一点优化,修改一下根目录下的build.gradle文件:
// common maven publishing configuration allprojects { group = 'org.elasticsearch' version = VersionProperties.elasticsearch description = "Elasticsearch subproject ${project.path}" // 增加下面部分 repositories { google() jcenter() // maven库 def cn = "http://maven.aliyun.com/nexus/content/groups/public/" def abroad = "http://central.maven.org/maven2/" // 先从url中下载jar若没有找到,则在artifactUrls中寻找 maven { url cn artifactUrls abroad } } }
4, 启动调试,以下命令会启动一个ElasticSearch实例,并且支持远程调试:
./gradlew run --debug-jvm
启动的ES实例的配置、数据等在 /distribution/build
目录。该命令执行后,会有一个短暂的编译过程,输出如下:
~/Elastic/ES/source/elasticsearch(6.6*) » ./gradlew run --debug-jvm Starting a Gradle Daemon (subsequent builds will be faster) > Configure project :benchmarks ======================================= Elasticsearch Build Hamster says Hello! Gradle Version : 5.1.1 OS Info : Mac OS X 10.14.6 (x86_64) JDK Version : 11 (Oracle Corporation 11.0.3 [Java HotSpot(TM) 64-Bit Server VM 11.0.3+12-LTS]) JAVA_HOME : /Library/Java/JavaVirtualMachines/jdk-11.0.3.jdk/Contents/Home Random Testing Seed : 416BC82E9B34077D [elasticsearch] Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release. > Task :distribution:run#start Running elasticsearch in debug mode, suspending until connected on port 8000 [elasticsearch] Listening for transport dt_socket at address: 8000 98% EXECUTING [2m 49s] > :distribution:run#start
看到这个输出后,对于IDEA,从菜单中选择: Run
-> Attach to Process…
,选择类似这样的进程:” node0/elasticsearch-/data (8000)
“。ES的启动类是 org.elasticsearch.bootstrap.Elasticsearch
,可在其main函数中打个断点,这样就能停住程序了。
其实整个环境搭建过程在ES源码目录下的
CONTRIBUTING.md
和
TESTING.asciidoc
文件中都已经说得很细了,以前就觉得elastic公司的产品文档写的非常好,比如ElasticSearch、Filebeat、Logstash等产品,现在看来,源码的文档也是非常棒,值得学习。正如有人是这样形容代码文档的( 老司机们发表下感受
):
Documentation is like sex; when it's good, it's very, very good, and when it's bad, it's better than nothing.
环境只是手段,阅读源码才是目的,万里长征第一步。最后借用Linus的一句话来结束本文:
Read the Fucking Source Code(RTFSC)。
注:原话出自 这里
(google group),本意大致是要表达”仔细阅读源代码后再向写代码的人提问题,否则无法进行有效的沟通“。