一、写在冬至前

12 月的第一周,寒潮还没来,需求已经排到了元旦。
白天写业务,晚上修 Bug,时间被敏捷迭代碾成粉末。
“能 1 秒搞定的事,绝不让它占用 2 秒。”
今天这篇文章,不谈架构,不画时序,只送你 7 个在终端里“复制即可提效”的 Java 命令行技巧。
全部亲测于 macOS/Linux/WSL2,Windows PowerShell 也给了替代方案。
每天节省 15 分钟,冬至前你就能提前 1 小时下班。


二、技巧 1:一键找到最耗 GC 的线程

jstat -gc -t $(jps -l | grep your.jar | awk '{print $1}') 1s 10 \
 | awk 'NR==1{print $0} NR>1{print $0 | "sort -k12nr"}'

输出示例:

Timestamp  S0C    S1C    ...  GCT
2025-12-02T19:18:08  512.0  512.0  ...  2.83

解读:
第 12 列 GCT 即 GC 总时间,按降序瞬间定位最耗时的 10 秒。
搭配 watch -n 1 即可实时监控:

watch -n 1 'jstat -gc -t $(jps -l | grep your.jar | awk "{print \$1}") 1s 1'

三、技巧 2:把线程栈按 CPU 使用率排序

top -H -p $(jps -l | grep your.jar | awk '{print $1}') -n 1 \
 | tail -n +8 | sort -k9 -nr | head -20

解释:
top -H 打出进程中所有线程;第 9 列是 CPU%;tail +8 去掉表头。
20 行里就能看见“哪个线程把 CPU 吃成了 100%”。
拿到线程 PID 后,秒转 16 进制:

printf "%x\n" <PID>

再去 jstack <pid> | grep -A 20 <nid> 即可定位代码行。


四、技巧 3:反编译任意类,只要 3 秒

场景:依赖包里的 class 没有源码,线上行为对不上。
终端里直接:

wget -qO- https://jitpack.io/com/github/your/lib/1.0.0/lib-1.0.0.jar \
 | jar xf - BOOT-INF/classes/com/xxx/Foo.class \
 && javap -c -p com.xxx.Foo > Foo.bytecode && less Foo.bytecode

解释:
javap -c -p 反汇编字节码,-p 把 private 方法也打出来。
不想写文件?CFR 实时反编译:

curl -sL http://www.benf.org/other/cfr/cfr-0.152.jar -o cfr.jar \
 && java -jar cfr.jar <(wget -qO- https://example.com/lib.jar) \
   com.xxx.Foo --decodelinenumbers

五、技巧 4:快速启动“零依赖”的 HTTP 文件服务器

调试前端或手机端,需要临时拉日志:
Java 8+ 自带 com.sun.net.httpserver

java -cp . -server com.sun.net.httpserver.SimpleFileServer \
     -p 8080 -d /var/log/your-app

一行命令,把 /var/log/your-app 变成静态站点。
浏览器访问 http://IP:8080/ 即可下载日志,无需 Nginx、Python、Node


六、技巧 5:把 System.out.println 重定向到 Socket

本地调试时,控制台被 IDEA 吃掉;远程环境又没 X11。
netcat 秒变远程控制台:

① 启动监听端(本地 Mac):

nc -lv 0.0.0.0 5000

② 应用启动参数里加:

java -Djavax.net.debug=ssl:handshake \
     -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 \
     -Djava.util.logging.config.file=logging.properties \
     -Djava.util.logging.SocketHandler.host=<本地IP> \
     -Djava.util.logging.SocketHandler.port=5000 \
     -jar your.jar

解释:
SocketHandler 把日志通过 TCP 推过来;nc 实时打印。
零代码入侵,老项目也能用。


七、技巧 6:一行脚本“热替换”class 并重新加载

本地开发不想重启 SpringBoot?
spring-boot-devtools + rsync

# 假设改了 target/classes/com/example/FooService.class
fswatch -o target/classes | while read; do
  rsync -az --delete target/classes/ \
    user@remote:/opt/app/BOOT-INF/classes/
done

远程只要开启 devtools,检测到 .class 时间戳变化即触发 restart。
保存即生效,比 Docker 卷挂载还快。


八、技巧 7:用 jbang 跑脚本级 Java

临时写个爬虫/数据处理,不想新建 Maven 工程?
jbang 让你像写 Python 一样写 Java:

# 安装(一次即可)
curl -Ls https://sh.jbang.dev | bash -s - app setup

# 新建脚本
jbang init --template=cli GistCrawler.java

编辑 GistCrawler.java

///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS org.jsoup:jsoup:1.17.2
import org.jsoup.Jsoup;
public class GistCrawler {
    public static void main(String[] args) throws Exception {
        var doc = Jsoup.connect("https://gist.github.com/discover").get();
        doc.select(".gist-file-name").forEach(e -> System.out.println(e.text()));
    }
}

运行:

jbang GistCrawler.java

无需 pom.xml,自动下载依赖,
适合一次性任务、GitHub Actions、CI 流水线。


九、彩蛋:把 7 个命令做成“今日书签”函数

复制到 ~/.zshrc~/.bashrc

# 用法:java_hacks gc
java_hacks(){
  case $1 in
    gc)   jstat -gc -t $(jps -l | grep your.jar | awk '{print $1}') 1s 10 ;;
    cpu)  top -H -p $(jps -l | grep your.jar | awk '{print $1}') -n 1 \
            | tail -n +8 | sort -k9 -nr | head -20 ;;
    http) java -cp . com.sun.net.httpserver.SimpleFileServer -p 8080 -d . ;;
    *) echo "Usage: java_hacks {gc|cpu|http}" ;;
  esac
}

今天试完,明天就能肌肉记忆。


十、收尾

技术的温度,不止于代码,更在于把省出来的时间拿去喝一杯热可可。
愿这 7 个命令行小技巧,让你在 2025 年最后一个月,
少加点班,多晒点太阳。

如果本文帮你节省了 1 小时,欢迎 点赞+收藏+评论 三连!
评论区告诉我:你最常用的 Java CLI 技巧是什么?


附:参考链接

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐