java进程远程调试
前言
一直以来,产线环境的问题总是很棘手。由于数据集、业务状态、压力规模等问题,很难在开发环境进行模拟。即使可以建立镜像的环境用来调试成本也是高昂的,这主要体现在建立这个环境所使用的时间,以及保持问题跟进需要耗费的时间和人力成本上,这里面服务器资源很多时候却不是最重要的虽然很多时候也很贵。所以,可靠的手段,除了前段时间我动脑筋的日志体系以外,远程进程的调试变成了一个像瑞士军刀一样的存在。有了它我基本上就有了跟踪所有问题的决心。介绍完背景后,开始聊正事吧。
怎么远程调试
远程调试其要点主要是这样几点:
- 调试:首先它是jvm的调试状态。其实这点和我们在运行ide的时候进行调试没有什么区别,原理也差不多。
- 远程:这里指的远程就是不是本机,其实就是对一个进程的调试。这需要远程进程开启一个监听端口,并且这边的ide以相应的协议和通信达成调试中需要的状态一直
- 对应版本的代码:这点很重要。并不是说我们随便启动拿一个代码就可以和远程进程进行调试了,需要是其对应版本的。那版本不一致会出现什么呢?不知道大家有没有过这样的体验。有的时候单步调试,发现代码会被调试到没有代码的地方,或者到了自己的断点哪里想要进入,结果却去了莫名其妙的地方。这个原因就是,代码版本不一致,它其实是按照真实的代码进行的跳转。而平常你之所以看到是运行步骤好像是跟着代码走的,其实是因为你的代码显示刚好和它的运行一致罢了,你那里没有代码它一样是这样跳转的。不过,原理性的东西我没有详细学习,基本就是这么回事啦。
被调试进程调整
平常的进程是不可以被调试的,需要用可调试状态启动进程才可被调试。我的命令被改造成了下面这样:
java -Xms128m -Xmx512m -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=18001 gz-lamp-web.jar
其中,-jar之后,gz-lamp-web.jar之前的部分是我为远程调试新增的代码,我们来看看它们什么意思。
-Xdebug
这个其实挺容易猜的,就是我上面说的,调试状态,这样启动进程就进入了调试状态。进入了调试状态,我们才可以使用调试的技术和今晨个交互
-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=18001
这个有些长,但它其实是一个参数。我们从头来:
-Xrunjdwp
这其实是这个参数的最顶级的定义,就是运行jdwp。什么是jdwp呢?
JDWP 是 Java Debug Wire Protocol 的缩写,它定义了调试器(debugger)和被调试的 Java 虚拟机(target vm)之间的通信协议。
所以,开启了这个通信,才能够进行交互,也就是我们的调试行为。
transport
通信协议自然需要知道怎么通信了,所以,transport之后就是通信参数的定义,也就是被调试进程在通信上呗设置成了什么样。
dt_socket
这是指调试进程和被调试进程使用socket的方式进行通信。这里还有个可选参数是dt_shmem,这是使用共享内存的方式进行通信。改参数仅适用于windwos平台。
server=y
这个参数的字面意思就是是否开启server模式,我们用y设置成了是。否的的话,将会以客户端的形式进行调试。区别是什么呢?就是真正的程序在哪运行。只要记住,只有server才是真正运行程序的那个就可以了。我的这个设置就是仍然以服务端的进程为运行进程,本地的只是调试客户端而已。
suspend=n
如果这个设置为y,则被调试进程将会等待,直到有调试进程连接进来才会继续运行。很明显我们不希望它等待,我们希望它继续运行。
address=18001
这个理解起来就比较容易了,这是调试通信占用的端口。注意不要和进程本身占用的其它端口冲突,否则会启动不起来。
文档
这是我逛网页的时候翻到的一篇oracle的官方文档,似乎有点旧了,不知道有没有新的:
https://docs.oracle.com/javase/1.5.0/docs/guide/jpda/conninv.html
调试进程设置
其实,理解了上面的内容,这里就很简单了。尤其是,我们有了Idea这样强大的IDE后,这个问题就更加简单了。先上个图吧:
为了清晰起见,我在图里做了一些说明。
首先,这个创建的是调试配置而不是项目或者模块,这个要搞清楚,是通过Edit Configeration进去的。然后,新建的是Remote配置。右侧的部分,我们选择的是附加在远程JVM上,使用Socket链接,地址和端口和被调试进程保持一致,切换焦点后命令行的部分会被自动生成出来,不用我们手动管理,如果需要特殊配置的话,记得选择JDK的版本。最后,选择你用来调试的模块就好了。当你用这个配置进行启动的时候,就可以正常的进入断点进行调试了。