1 背景
最近在从Go程序员切换成Java程序员,在前期需要解决的一个重要问题就是在VS Code编辑器中如何进行Java代码的调试。
调试,是程序员的必备基础日常技能。
参加工作以来,自己学习的第一门语言是PHP,当时调试的主要手段是var_dump/echo和打印log,写的很嗨皮。19年学习go语言后,接触到delve调试工具,遇到一些比较难解的case均通过delve工具来解决,但很惭愧,自己的delve工具均是通过shell在命令行环境下进行调试,如果项目代码比较庞大,shell确实效率低一些。自己不用编辑器的原因是自己的笔记本电脑并不是自己的开发环境,有过工作的童鞋有了解,笔记本电脑一般都是「UI层」,代码需要跑在开发机(Linux)上,开发机与线上的环境基本一致,后续的agile流水自动集成和线上部署均是丝滑的。示意图如下。
问题在哪里呢,问题就是出在本地环境Mac和开发环境Centos环境不一致这个上面。
这里得稍微赘述下,Go语言是编译型语言,Java比较特殊,可以说是编译型的语言,也可以说是解释型的语言,这里为陈述简单,暂且将为归类为编译型语言。
2 学习过程
2.1 「农业时代」 JDB
由于在Go中用shell的dlv习惯了,所以Java应该也有对应的shell命令,查了下是JDB。调试过程如下
0. 安装JAVA基础环境
- 下载JDK https://www.oracle.com/java/technologies/downloads/
- 解压,设置对应的环境变量
# 编辑
# vim /etc/profileexport JAVA_PATH=/home/work/new/jdk1.8.0_351/bin/ export PATH=$JAVA_PATH:$PATH # 生效
# source /etc/profile - 安装成功标志
$ java -version java version "1.8.0_351" Java(TM) SE Runtime Environment (build 1.8.0_351-b10) Java HotSpot(TM) Server VM (build 25.351-b10, mixed mode) $ javac -version javac 1.8.0_351
A. 准备一个源程序
目录结构如下(bin下的HelloJDB.class是后来生成的)
. ├── bin │ └── HelloJDB.class └── src └── HelloJDB.java
./src/HelloJDB.java 源代码如下
1 public class HelloJDB { 2 public static void main(String[] args) { 3 int i = 5; 4 int j = 6; 5 int sum = add(i, j); 6 System.out.println(sum); 7 8 sum = 0; 9 for(i=0; i< 100; i++) 10 sum += i; 11 12 System.out.println(sum); 13 } 14 15 public static int add(int augend, int addend){ 16 int sum = augend + addend; 17 return sum; 18 } 19 }
B. 编译源代码
javac -g -d bin/ src/HelloJDB.java
生成的class文件在 ./bin 目录下
C. 开始调试
$ cd ./bin/
$ jdb -sourcepath ../src/:. HelloJDB
../src 找到java文件,方便调试过程中看源代码
: 分隔符号
. 当前class目录
Initializing jdb ...
在主函数下断点 > stop in HelloJDB.main Deferring breakpoint HelloJDB.main. It will be set after the class is loaded.
运行 > run run HelloJDB Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable > VM Started: Set deferred breakpoint HelloJDB.main Breakpoint hit: "thread=main", HelloJDB.main(), line=3 bci=0 3 int i = 5; 运行一步 main[1] step > Step completed: "thread=main", HelloJDB.main(), line=4 bci=2 4 int j = 6; 查看当前的运行位置 main[1] list 1 public class HelloJDB { 2 public static void main(String[] args) { 3 int i = 5; 4 => int j = 6; 5 int sum = add(i, j); 6 System.out.println(sum); 7 8 sum = 0; 9 for(i=0; i< 100; i++) 10 sum += i;
打印i main[1] print i i = 5 main[1] quit
总结,用jdb体验感觉比较差,感觉没有dlv用的丝滑(dlv debug main.go 开始调试),单步调试和加断点在shell中操作也比较麻烦。痛定思痛,上编辑器调试。
2.2 「工业时代」VS Code
用VS Code面临的第一个问题是我们的项目代码是在本地上还是开发机上。 这样描述还不够精确。
引用大佬的一段话,感觉描述的挺准确的。
如果按照代码位置再区分 local 还是 remote ,那么姿势就可以分为:
- 本地 launch 调试:vscode 在本机,代码在本地,二进制在本地;
- 本地 attach 调试:vscode 在本机,代码在本地,进程在本地;
- 远程 lanuch 调试:vscode 在本机,代码远端,二进制在远端;
- 远程 attach 调试:vscode 在本机,代码在本地,二进制在远端;
这里我们首先考虑情况4,这种最为强大(坑也多)
在进行调试之前,要做的准备工作是,在MAC电脑上安装 Java/Maven,保持与Centos上面的Java/Maven保持一致的版本。maven下载地址,https://maven.apache.org/,maven解压后设置环境变量。另外,准备好一个maven项目(简单的项目不用maven也是ok的,用maven是为了贴近实际的情况)
开发机上运行,确保项目可以正常启动,8000端口已经正常启动
mvnDebug spring-boot:run -Dspring-boot.run.jvmArguments="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000"
本机MAC上启动VS Code,先下载插件 Debugger for Java,如下图
将开发机的maven项目代码copy到本地一份。
注意!!!,目录一定是./src目录,不能是上层或者下层,否则vscode调试会报错(这个坑踩了,耽误了不少时间)。
具体的tree目录如图所示才可以,一定注意。
下面开始操作啦,点击创建launch.json
选调试器 Java
生成的文件如下,其实这个文件就会生成在顶级目录下,
修改内容如下,保持,之后重启项目
{ "type": "java", "name": "Launch BlogserverApplication", "request": "attach", // 远程attach模式 "hostName": "xxx", // 开发机hostname "port": "8000", // 开发机开的端口,上面mvnDebug开的是哪个端口,这个就填写哪个端口 "projectName": "blogserver", "sourcePaths": ["/Users/xxx/Downloads/VBlog-master/blogserver/"] // 重要~~!!!~~本地的代码位置,方便待会加断点
}
开始调试
看到开发机上的服务已经启动了,就说明已经attach上去了
如果展示不出来这个地方,可以点下重启,亲测有效
加断点,开始调试,随便找一个地方加一下
因为我这个项目是http的服务,curl一下,可以看到已经捕捉到
之后就可以开心的调试啦,看着内容很多,其实掌握几个关键点之后,还是比较容易掌握的。
3 提炼出来的经验
1 遇到不懂的问题,需要慢下来,慢下来一点点看,越着急找到答案,可能反而容易乱
2 针对不懂的基础问题,不能绕过,直面问题,而且一定要把这类基本问题通过输出的方式沉淀下来,通过输出才能倒逼自己把这块盲点吃透
3 看别人博客/看书学会->第一级,能够调通/跑通->第二级,写文章输出->第三级,帮别人解决类似问题->第四级,基础问题基本上要达到第四级的标准
4 技术原理
最核心的技术原理是JDB ATTACH。vscode为啥可以通过sourcePaths 参数直接下断点,这是因为,本地代码和开发机的相同,在这里下断点,相当于vscode帮我们加了断点。所以可以做到「看起来在本地调试,其实是调试远端程序的过程」
5 参考文章
[0] vscode 官网文档 https://code.visualstudio.com/docs/java/java-debugging
[1] JDB调试 简单java程序调试 https://www.cnblogs.com/rocedu/p/6371262.html
[2] java调试那点事 https://developer.aliyun.com/article/56
[3] vscode 调试技巧 https://www.modb.pro/db/377704
标签:Code,Java,int,HelloJDB,VS,java,main,调试 From: https://www.cnblogs.com/maxiaotiaocode/p/16899746.html