在 VSCode 里做 Java 开发,很多人第一反应是装插件、点那个绿色 Run 按钮,但真正开发效率拉开差距的地方,是集成终端里的命令操作。红帽 Java 插件、Java Extension Pack 这些扩展能帮你补全代码、识别 Maven/Gradle 工程,可日常跑构建、查 JVM 状态、清理分支、回滚代码、排查端口占用,十有八九还是要回到命令行。这里把我这几年在 VSCode 里高频用到的 Java 开发命令整理成一份清单,按环境准备、编译调试、构建工具、版本控制、故障排查这条主线讲,适合刚搭完环境的新手,也适合偶尔忘记命令的老手直接查。
1. 环境准备阶段的命令:先解决 JDK 和插件,再谈写代码
很多 Java 项目在 VSCode 里一打开就报编译错误,不是代码的问题,而是 JDK 位置不对、扩展没装全。先把底子打牢,后面所有命令才会听话。
1.1 用命令确认 JDK 环境和 JAVA_HOME
Windows 上最偷懒的安装方式是winget install Microsoft.OpenJDK.21,装完默认路径通常带空格,例如C:\Program Files\Microsoft\jdk-21.0.2。这个空格在 IDE 里一般没事,但在命令行拼接路径时容易出幺蛾子,尤其是自定义脚本和 gradlew 里。所以装完第一件事,是把JAVA_HOME系统环境变量设置好,同时把%JAVA_HOME%\bin加到 PATH。
为什么一定要单独配JAVA_HOME?因为 Maven、Gradle 和不少构建插件不读 PATH,它们默认找JAVA_HOME。VSCode 的 Java 语言服务虽然会自己扫描机器上的 JDK,但扫描逻辑不一定认你手动指定到特定目录的那套配置。配完之后,打开 VSCode 的集成终端,依次跑这三条:
java -version javac -version echo $JAVA_HOMEWindows 的 CMD 里最后一条是echo %JAVA_HOME%,PowerShell 和 Git Bash 里用echo $JAVA_HOME。如果java -version正常但javac提示找不到,说明 PATH 里有两个 JDK 混着,java匹配到的是系统目录下的运行时,而javac不在同一个 bin 里。这种环境分裂会导致 VSCode 语言服务编译时用 A JDK、终端构建时用 B JDK,隐蔽得很。
macOS 和 Linux 上我推荐用 sdkman 管理 JDK,命令比改环境变量快很多:
sdk list java sdk install java 21.0.3-tem sdk default java 21.0.3-tem换完 JDK 之后记得重开一个 VSCode 窗口,因为集成终端启动时读了一次环境变量,老窗口不会自动感知新配置。刷一下source ~/.bashrc也行,但 VSCode 里的 Java 语言服务仍要重启才彻底干净。
有个实操小坑:新版 VSCode Java 扩展已经不建议在settings.json里写java.home,而是直接依赖系统JAVA_HOME。如果启动时提示 “Java runtime could not be found”,不要再翻旧教程加java.home,应该去settings.json里检查java.configuration.runtimeDirs设置,或者修好系统环境变量后重启。
1.2 用命令行管理 VSCode Java 扩展,换新机器不再点鼠标
换一台电脑或者给同事初始化开发环境,手动去扩展商店搜索 Java Extension Pack 再点安装,慢得让人想撞墙。VSCode 的命令行工具code可以直接安装扩展,一条命令搞定:
code --install-extension redhat.java code --install-extension vscjava.vscode-java-packvscjava.vscode-java-pack会一次性装好调试器、测试运行器和 Maven/Gradle 工具,日常开发足够。特定场景再补几个:
code --install-extension vmware.vscode-spring-boot code --install-extension vscjava.vscode-java-debug code --install-extension vscjava.vscode-java-test code --install-extension sonarsource.sonarlint-vscode查看已经装了哪些、什么版本:
code --list-extensions --show-versions卸载不再需要的:
code --uninstall-extension redhat.java公司内网环境不能访问扩展市场时,把插件市场上对应的.vsix文件下载到本地,然后直接指定文件路径安装:
code --install-extension ./vscjava.vscode-java-pack-0.25.0.vsix我用命令行管理插件之后,发现一个额外好处:可以用脚本统一维护团队开发规范里的插件列表。新建一个extensions.txt,每行一个插件 ID,新机器上循环执行安装命令即可,再也不用来回对版本。
2. 编译、运行和调试命令:VSCode 里那些隐藏的 JVM 玩法
这个阶段要回答一个很实际的问题:当 IDE 图形化按钮不够用的时候,怎么拿命令把项目跑起来、怎么定位调试会话对应的 JVM、怎么处理端口被占用。这三个问题在 VSCode 里几乎每天都可能碰到。
2.1 手动编译与运行:小型项目不想建 Maven 时的备用方案
没有 Maven/Gradle 的纯 Java 项目在 VSCode 里也能跑,但很多时候三角号按钮会失效,原因是没有正确的 classpath。此时终端手动编译最可靠:
javac -encoding UTF-8 -d out src/com/example/Main.java-d out指定字节码输出目录,-encoding UTF-8是 Windows 上必须带的,不然中文注释和字符串字面量可能变成乱码导致编译失败。如果你手里有多个源码文件,直接写src/**/*.java在 Windows 的 CMD 里有时展开不正常,更稳的做法是让 shell 帮你展开,Git Bash 和 macOS 终端下写成javac -d out src/com/example/*.java。
编译完运行,要把 classpath 指向out目录,并且包路径要和目录结构一致:
java -cp out com.example.Main如果依赖第三方 jar,Windows 下 classpath 用分号分隔,Linux/macOS 用冒号:
java -cp "out;lib/*" com.example.Main java -cp "out:lib/*" com.example.Main注意lib/*这种通配符是 Java 自己支持的,不用把目录里每个 jar 都列出来。打成可执行 jar:
jar --create --file app.jar --main-class com.example.Main -C out . java -jar app.jar手动敲这些命令的次数不会很多,但一旦 VSCode 里出现 “Build failed” 或者运行按钮是灰色,手动编译报错信息比 IDE 的折叠日志清楚得多,能直接看出是缺依赖还是路径写错。有时候在调试类加载问题时,我还会开一个jshell,把可疑的类 new 出来直接跑两行,确认 API 行为,比等 IDE 启动快很多。
2.2 调试时查看 JVM 进程和线程堆栈
VSCode 调 Java 时,每个 debug session 会启动独立的 JVM,多个 session 一起开会看到一堆 java 进程,很容易搞混。先用jps列出所有 Java 进程和主类入口:
jps -l输出类似:
19280 com.example.Main 21780 org.gradle.launcher.daemon.GradleDaemon 22136 sun.tools.jps.Jps如果项目是用 Spring Boot 跑的,jps -l输出的就是主类全限定名,非常直观。基于这个 PID 继续定位:
jcmd <pid> help jcmd <pid> Thread.print jstack <pid> > thread_dump.txtjcmd Thread.print和jstack都能打出线程堆栈,jstack适合重定向到文件再慢慢看,jcmd的响应格式稍微新一点。排查死锁、线程阻塞、CPU 高居不下时,线程 dump 就是救命稻草。
看堆内存和 GC 状况用这几条:
jmap -heap <pid> jstat -gcutil <pid> 1000jstat -gcutil后面那个1000表示每秒打一次指标,配合 VSCode 里的 Java 调试控制台变量观察,能基本判断 Full GC 是否频繁。有一点要注意:jps、jcmd必须要和进程实际使用的 JDK 同版本同用户,否则可能提示连接不上,很多老程序员在排查问题时莫名被这里卡住。
2.3 端口占用与进程结束后台残留
Spring Boot 项目最经典的报错是Port 8080 was already in use。在 VSCode 终端里,Windows 用:
netstat -ano | findstr :8080拿最后一列的 PID,强制结束进程:
taskkill /F /PID 12345macOS 和 Linux 用lsof:
lsof -i :8080 kill -9 12345有时候端口占用是 VSCode 调试任务强制中断留下的残留 JVM,用上面的思路处理即可。我建议每台开发机记住这两个组合命令,因为它们不仅是开发环境排查利器,面试八股里也是高频面试题。
3. Maven/Gradle 构建命令:日常用得最多、最容易出细节问题的一批
这是 VSCode Java 开发里真正的高频工作区。很多人觉得侧边栏有 Maven 面板就够了,但面板很难传参,比如跳过测试、指定模块、单跑某个 Test 类,还是得回到终端。我按 Maven 和 Gradle 分开讲,顺手把实体类生成建表 SQL 的需求也归到这里,因为这种操作本质上也是“用命令触发代码生成”。
3.1 Maven 高频命令的参数差异与多模块陷阱
开发阶段我常用的命令其实就那么几条:
mvn clean compile mvn test mvn clean package -DskipTests mvn spring-boot:run mvn install-DskipTests是编译测试代码但不运行测试,打包速度快。真正想连测试代码都不编译,要换成-Dmaven.test.skip=true。这两个参数的效果容易记混,我在 VSCode 的终端里吃过一次亏:改了业务代码后跑mvn package -Dmaven.test.skip=true,测试模块没编译,整个 build 是绿的,但老测试代码里的语法错误被掩盖了,上线前全量构建才发现。
排查依赖树,尤其是 spring 相关 jar 版本冲突:
mvn dependency:tree -Dincludes=org.springframework:*只看某个模块的依赖关系,加-pl和-am:
mvn -pl shop-service -am clean package-pl shop-service指定模块,-am同时构建它依赖的其他模块。多模块工程在 VSCode 里直接点 Maven 面板的 package,经常因为你当前打开的那个模块没有依赖关系而失败,所以终端命令反而更顺手。
离线环境构建:
mvn -o clean package-o是 offline,离线时如果本地仓库缺依赖会立刻报错,记住一次性把所有依赖 build 完整再断网。
有个必须提的点:如果公司用内网 Maven 私服,或者网络不稳定,maven 从中央仓库拉依赖会慢到怀疑人生。解决办法是编辑~/.m2/settings.xml里的 mirror,把中央仓库指向国内镜像服务。换完源跑一次mvn dependency:resolve,能明显感到拉依赖变快。这个问题在 VSCode 的 Java Language Server 初始化阶段尤其重要,因为后台要扫描全部 classpath。
3.2 Gradle 高频命令和守护进程的坑
Gradle 风格的项目,我建议一律使用项目根目录的gradlew包装器,而不是系统全局的 gradle,这样保证整个团队版本一致:
./gradlew tasks ./gradlew build --console=plain ./gradlew clean test--console=plain在 VSCode 集成终端里很重要。默认的彩色进度输出在非 TTY 环境下会把日志刷得乱七八糟,加上纯文本模式后错误信息可读性高很多,还能避免终端里出现一堆控制字符。
日常调试 Spring Boot 项目:
./gradlew bootRun或者调试模式下才需要的任务列表:
./gradlew tasks --allGradle 默认会启动守护进程,长时间开发后它会占用不少内存。有人改了build.gradle,发现新配置死活不生效,多半是守护进程缓存了旧状态。执行:
./gradlew --stop再看是不是还挂着 GradleDaemon 进程,需要的话可以 kill 掉。VSCode 里如果提示找不到 Gradle 或 Java 版本不匹配,先确认系统JAVA_HOME和项目要求版本是否一致,因为 Gradle 用的是它自己发现的 JDK,不是 VSCode Java 插件选的那一个。
3.3 从 Java 实体类生成建表 SQL:用 JUnit 命令替代手写 DDL
很多项目用了 MyBatis-Plus,实体类和表结构强相关,经常需求变一下,就要同步改 CREATE TABLE,手写又累又容易漏字段。我见过不少人是写一个 JUnit 测试类,通过反射遍历实体的字段,拼出 DDL 输出到控制台,然后在 VSCode 里面右键运行测试类;命令行方式就是:
mvn test -Dtest=GenerateTableTest或者用 Gradle:
./gradlew test --tests GenerateTableTest这样生成 DDL 的好处是字段类型、长度可以直接从注解元数据中解析,不会出现在建表脚本和实体类不一致的情况。更正规一点的生产方案是引入 Flyway 或 Liquibase,把 DDL 脚本纳入版本控制:
mvn flyway:migrate mvn flyway:info我的习惯是:实体类驱动生成 SQL 只适合原型阶段,正式环境尽量走 Flyway。这样表结构变更有了历史记录,VSCode 里团队协作时不会出现“一人改了实体类,另一人本地表结构还是旧的”这种尸横遍野的场面。
4. Git 命令:VSCode 里清理分支、回滚和反悔的操作
Git 图形界面能覆盖 80% 的需求,但剩下 20% 恰恰是最容易误操作的部分。比如远程分支被队友删除后,VSCode 的源代码管理视图里明明还挂着那个分支,怎么也点不掉;又比如 reset 之后想反悔,图形界面根本没有入口。这些都是终端的强项。
4.1 在 VSCode 终端里清理远程已删除的“幽灵分支”
VSCode 的 Git 视图不会自动感知远程删除的分支,所以屏幕上会出现一堆指向不存在的origin/xxx的条目。手动刷新也不行,需要用命令裁剪:
git fetch --prune或者:
git remote prune origin执行完之后再打开源代码管理视图,那些幽灵分支都消失了。这时候本地如果还留着对应分支,可以进一步清理。查看哪些本地分支已经合并过、可以安全删除:
git branch --merged然后删除指定分支:
git branch -d feature/old-version没有合并过会删除失败,如果你确定这些改动不要了,用大写 D 强制删:
git branch -D feature/abandoned批量删除所有已合并的本地分支,可以这样:
git branch --merged | grep -v 'main\|master' | xargs git branch -dWindows PowerShell 没有 grep,需要换成:
git branch --merged | Select-String -NotMatch 'main|master' | ForEach-Object { git branch -d ($_.Line.Trim()) }实测这个组合在 VSCode 的 PowerShell 终端里很好用,一次能清理十几条杂分支。注意别把当前分支误删了,细看git branch输出里带*的是当前分支。
4.2 回滚代码到底用 reset 还是 revert
很多人在 VSCode 里用git reset --hard之后就后悔了。这两个命令的分水岭在于:这个分支是否已经推送到远程被别人使用。
本地分支、还没推送,撤销最近一次提交:
git reset --hard HEAD~1这条命令会直接丢弃提交记录,本地历史回到上一个节点,工作区也强制覆盖。
已经推送到共享远程分支,就不该再用 reset 改写历史,而是用 revert 生成一个反向提交:
git revert <commit-hash>这样远程历史不会被重写,只是新增一个“撤销刚才修改”的提交,其他人 pull 的时候不会出现分叉冲突。
另外两个高频场景:
放弃工作区某个文件的未提交修改:
git restore src/main/java/com/example/Main.java取消暂存区里的文件,但保留工作区改动:
git restore --staged src/main/java/com/example/Main.java临时把当前手头工作藏起来:
git stash push -m "temp: 改造登录逻辑" git stash list git stash pop4.3 用 reflog 找回误删的提交和丢失的分支
git reset --hard HEAD~1之后如果发现刚才删掉的提交里还有想要的东西,别慌,git reflog能看到所有 HEAD 移动轨迹:
git reflog --oneline -10输出每一行的最前面是一个 commit 哈希,找到当前 HEAD 之前的那个记录,执行:
git reset --hard <那个哈希>提交就找回来了。同理,git branch -D误删分支后,也可以先用 reflog 找到分支最后一次指向的 commit,再用git branch 新分支名 <哈希>恢复。VSCode 图形界面里没有 reflog 入口,所以这条命令我一直记着,关键时刻救过几次命。
5. 故障排查命令速查表:一张表覆盖高频异常
接下来把上面提到的排查命令按场景汇总成一张速查表,遇到问题先对着场景找命令,比记住所有命令更高效。
| 场景 | 典型现象 | 定位命令 |
|---|---|---|
| Java 进程找不到了 | 服务突然挂掉 | jps -l、jcmd <pid> help |
| CPU 使用率飙升 | 应用卡顿、线程死循环 | jstack <pid> |
| Full GC 频繁 | 内存吃紧、接口变慢 | jstat -gcutil <pid> 1000 |
| 堆内存溢出 | OOM 报错 | jmap -heap <pid> |
| 端口被占用 | Port 8080 was already in use | Windows:netstat -ano | findstr :8080然后taskkill /F /PID 12345;macOS/Linux:lsof -i :8080然后kill -9 12345 |
| Maven 构建慢 | 下载依赖卡住 | 检查~/.m2/settings.xml镜像源 |
| 依赖版本冲突 | NoSuchMethodError 等奇怪报错 | mvn dependency:tree -Dincludes=org.springframework:* |
| 远程分支幽灵列表 | Git 视图出现已删分支 | git fetch --prune/git remote prune origin |
| 误删提交或分支 | 代码丢失 | git reflog --oneline -10 |
| 集成终端输出乱码 | 中文编译或日志乱码 | javac -encoding UTF-8,JVM 加-Dfile.encoding=UTF-8 |
这张表最大的价值不是背命令,而是给自己的排查过程建立一个“先看现象、再选工具、最后下结论”的路径。比如 CPU 高,先用top或任务管理器确认是哪个进程占的,如果是 java,再jstack看线程。一上来就 jstack 可能大规模刷屏,反而不容易找到问题线程。
6. 常见问题与避坑实录:终端里踩过的坑,按经验写下来
最后分享几个我实际踩过很多次、每次都能坑到人的细节。这些不算大问题,但一旦踩到,排查时间以小时计。
6.1 环境变量、编码和 VSCode 缓存问题
JDK 路径带空格是老话题,但几乎每台 Windows 新机器都会碰到。VSCode 自己的集成终端还好,尴尬的是在 tasks.json 里配置自定义任务时,command拿不到JAVA_HOME,你拼接的路径里一旦有空格就整个崩掉。解决办法不是不加空格,而是规范目录:给 JDK 设一个无空格路径,或者配置系统环境变量,不要只在 VSCode 的 settings 里写。装完 JDK 顺手把JAVA_HOME和 PATH 配好,能省掉未来无数个Error occurred during initialization of VM。
编码问题在 Windows 上尤其隐蔽。项目里全部文件是 UTF-8,但印章默认区域是 GBK,javac不指定编码就把源码按 GBK 去读,中文注释时常出现“非法字符”之类的报错。VSCode 的 Java 语言服务一般是 UTF-8,和终端编译出来的结果对不上,会造成“IDE 显示正常、命令行编译失败”的错觉。统一在.vscode/settings.json里写:
{ "terminal.integrated.defaultProfile.windows": "Git Bash", "files.encoding": "utf8", "java.configuration.updateBuildConfiguration": "automatic" }但注意 VSCode 的集成终端并不会自动继承 VSCode 设置的编码,它继承的是系统区域和 shell 的配置。遇到编译乱码,最有效的还是javac -encoding UTF-8。
Java Language Server 缓存损坏也是头疼事。症状是重命名全局失效、类名补全乱七八糟、报一些根本不存在的方法错误。在命令面板执行Java: Clean Java Language Server Workspace后重启窗口,大多数问题能解决。这个操作会重建索引,大项目可能要等一两分钟,但比手动删缓存目录靠谱。
6.2 我自己的终端工作流和收尾建议
说完这些坑,分享一个我一直在用的操作习惯:在.bashrc或者 PowerShell profile 里给高频命令设置别名。
alias jps='jps -l' alias mcp='mvn clean package -DskipTests' alias gprune='git fetch --prune && git remote prune origin' alias gmerged='git branch --merged | grep -v "main\|master" | xargs git branch -d'这几个别名覆盖了日常最频繁的构建、分支清理、进程查看三类操作,配合 VSCode 的集成终端,效率比从图形界面点七八下快得多。最顺手的一点是gprune,一行命令把本地分叉和远程幽灵分支都清理掉,Git 视图瞬间清爽。
如果你现在刚接触 VSCode Java 开发,别急着一次性记全部命令,先把第 1 章的 JDK 检查、第 2 章的端口排查、第 4 章的分支清理这三块用熟,已经能应付大多数日常工作。第 3 章的构建命令是加分项,等 Maven/Gradle 工程跑起来之后,自然会发现终端比侧边栏可控得多。命令这东西,不是拿来背的,是拿来用的。