⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 juejin.cn/post/6844904071204339725 「Vt」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

正文

回到正题

说到远程Debug这个功能,基本上大多IDE都会自带,但是一般情况下还真是很少用,大概是因为...

Just a joke😄,不要当真

笔者切换到IDEA之后,还真再就没用过远程Debug,直到昨天发现了一个非常基础的错误...

坑从何来

坑来自于我的开源小工具:

https://gitee.com/vtDev/v-mock

笔者本意是打造一个,简单,轻巧,一键运行的接口模拟系统,用来方便等待他人接口的前端后端同学。

基于以上目的,我使用了嵌入式数据库sqlite,来配合Springboot,构造了无须配置,一行启动的小jar包. 目录结构如下,数据库直接扔在了Resource中:

开源后有使用的同学提了Bug,笔者也是正常操作,改完bug重新打版发行.

升级版本的同学,发现数据没了,笔者暂时给出了方案,嵌入式数据库嘛,把旧jar中的DB文件,覆盖到新Jar中就好了

(DB文件位于jar包中的位置)

说出这句话的时候,也不能完全赖🧠瓦特了,毕竟Springboot+Sqlite这种奇葩组合也是为了工具的小巧性,偶尔尝试的产物.

Spring Boot 基础就不介绍了,推荐下这个实战教程: https://github.com/javastacks/spring-boot-best-practice

事实上稍微想想,db文件和其他资源不一样,是要频繁改写的,当然改动的不是jar包中的原始文件.

直到收到了一个Issues,告诉了笔者DB文件复制到新jar中并没有生效.

笔者也迅速反应过来,怎么可能用的jar内的DB文件,真实文件不出意外是放在java.io.tmpdir下了.

java.io.tmpdir的路径,一般情况下,macos是在$TMPDIR,win则在%temp%.

笔者也切换到了对应的目录,终于看到了jar运行时真实使用的DB文件:

但是这个命名方式很奇怪啊,和原本的v-mock.sqlite并不沾边.

一路追随sqlite的jdbc驱动源码,找到了org.sqlite.SQLiteConnectionextractResource方法,看到了命名代码:

其实看到这已经清晰了,源码中使用了sqlite-jdbc-tmp拼接了原始jar中DB文件的URL类的hashcode作为文件名.

之所以笔者开发的时候没注意到,看看这个方法第一个if判断就知道了。

笔者习惯用IDE中的Springboot或者Application模式直接启动项目,并不是打包后的启动方式

所以当Protocolfile而不是jar的情况,直接就使用了target/classes/db/v-mock.sqlite文件,不用生成临时文件.

开发时,DB可视化工具也连接的是target/classes/db/v-mock.sqlite,所以当时并没发现疑点.

事实上这是很正常的操作,很多地方的源码都有判断是普通web环境还是以jar运行的,如果有这方面的调试,要思考你的启动方式了.

那么想把断点打在第一个if之后,看到效果,选择之一就是可以使用远程Debug的方式。

IDEA的远程Debug

IDEA的远程Debug模块真的是设计十分贴心,傻瓜操作,命令都生成好了,不知道现在的eclipse版本有没有这么贴心.

从configuration中搜索remote模版,点击右上角的create configuration,就创建好了一个远程debug启动方式.

Debugger mode选择Attach to remote JVM即可,它还有一个选项是Listen to remote JVM,意如其名嘛,一个是主动附着到启动的程序,一个是被动监听程序。

ip和端口不用多说,笔者直接用的本地jar包,所以填了localhost,右边jdk版本如果使用其他版本的,需要调一下。

中间的文本框就是生成好的jvm参数了,非常人性化了,直接加入启动命令即可 java -jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 v-mock.jar

可以完全不用管命令什么意思,如果你想知道,笔者也大概解释一下:

  • -agentlib:jdwp 最重要的参数,启动JDWP代理,JDWP全称就是Java Debug Wire Protocol,官方给的方便调试的工具.
  • transport=dt_socket 通过socket方式传输数据,dt八成就是data transfer的缩写了.
  • server=y 开启调试server端,注意,因为笔者上文选择的是Attach to remote JVM,所以这里才是y,等待有调试器Attach过来,如果你选了Listen模式,那么就是反过来的,调试器是server,这里就是n了.
  • suspend=n 是否挂起,这里设置为n,也就是说程序正常跑,什么时候需要Attach就去Attach即可,如果设置为y,程序将会等待调试器Attach上才会继续执行,比如启动源码的调试场景.
  • address=5005 调试端口设置为5005,当然其它端口也可以.

启动jar包,再以刚才创建的方式进行debug,期待的断点位置已经成功到达了。

文章目录
  1. 1. 正文
  2. 2. 坑从何来
  3. 3. IDEA的远程Debug