1. 条件断点循环调试的终极武器第一次遇到需要调试包含300次循环的代码时我差点把显示器砸了——每次手动检查变量值简直是在折磨自己。直到发现IDEA的条件断点功能才明白原来调试循环可以这么优雅。条件断点的本质是给普通断点加上if判断。在IDEA中对着断点红点右键会看到Condition输入框。比如这段商品库存检查的代码for (Product product : productList) { // 当库存低于5时触发断点 if (product.getStock() 5) { System.out.println(库存预警 product.getName()); } }我们可以在循环行设置断点后右键输入条件product.getStock() 5。实测发现几个实用技巧条件表达式支持方法调用比如product.isOffline() product.getPrice() 100复杂条件可以用、||组合但要注意避免副作用勾选Suspend when false可以实现反向中断提示条件表达式里不要修改程序状态比如避免写user.setName(test)这样的操作最近帮同事排查一个分页查询的bug就是在循环条件里设置了pageNum 3 list.size() 0直接定位到第四页数据异常的情况效率提升十倍不止。2. 断点回退时光倒流的神奇能力上周排查一个订单状态异常问题时我眼睁睁看着变量被错误修改却无能为力——直到想起IDEA的断点回退功能。这个被很多人忽视的功能实际上是调试界的后悔药。具体操作分三步在需要观察的方法开始处打普通断点触发断点后在Debug窗口找到Drop Frame按钮点击后程序指针会回到方法入口所有局部变量恢复初始值我常用它来复现某些偶现bug的触发条件检查方法不同输入对应的输出验证参数校验逻辑的边界情况public String processOrder(Order order) { // 断点打在这里 if (order.getAmount() 0) { adjustOrder(order); // 想看看这个方法如何修改order } return doProcess(order); }注意回退操作不会恢复已经修改的静态变量或数据库数据这点需要特别注意有次排查支付金额计算错误就是通过反复回退调试发现是某个静态变量被其他线程修改导致的。如果不用回退功能可能要加十几行日志代码才能发现问题。3. 表达式执行运行时修改的超能力记得有次凌晨两点排查生产问题发现某个配置值错误导致流程中断。当时灵机一动用表达式执行临时修复等第二天再发正式补丁——这个功能救过我好几次命。在调试暂停时有几种方式执行表达式Watch窗口持续观察某个表达式值Evaluate Expression临时执行任意代码快捷键AltF8代码片段注入直接在编辑器里写临时语句public class DiscountService { public double calculateDiscount(User user) { double discount 0; // 在这里暂停 if (user.isVIP()) { discount getVipDiscount(); // 想测试不同折扣率 } return discount; } }调试时可以在Watch窗口添加user.getLevel() 2按AltF8输入user.setVIP(true)甚至直接执行discount 0.3覆盖原值我常用的几个骚操作快速构造测试数据new User(test, 18)模拟异常场景throw new RuntimeException(test)动态修改变量collection.add(debug_item)重要生产环境慎用此功能可能造成数据不一致4. 强制中断紧急止血的调试技巧去年处理过一个无限循环发送短信的线上事故当时就是靠强制中断功能及时止损。这个功能特别适合处理无限循环或递归耗时的批量操作需要立即中断的危险操作在IDEA中有两种中断方式Force Return立即从当前方法返回可指定返回值Throw Exception强制抛出指定异常public void batchProcess(ListData list) { for (Data data : list) { // 发现处理到第1000条时出错 process(data); // 想跳过后续处理 } }操作步骤在process方法内暂停右键选择Force Return或者选择Throw Exception抛出业务异常我遇到过最惊险的情况是发现循环里在误删数据库记录立即Force Return停止删除然后通过回退功能找出bug原因警告强制中断可能导致对象状态不一致仅限紧急情况使用5. 异常捕获空指针问题的克星空指针异常是Java开发者的老朋友但定位起来往往费时费力。IDEA的异常断点功能就像给代码装了异常雷达。设置方法点击Debug窗口的View BreakpointsCtrlShiftF8添加Java Exception Breakpoint勾选NullPointerException可以指定具体类或包范围public class OrderService { public void process(Order order) { // 实际业务中这里可能有10层嵌套调用 String address order.getUser().getAddress().getCity(); } }当空指针发生时程序会自动停在异常抛出点变量窗口显示所有相关对象可以立即看到哪个环节出现null我总结的最佳实践配合条件过滤order ! null order.getUser() null记录异常现场勾选Log message to console临时修复在异常处用表达式给null对象赋默认值有次解决一个偶现的空指针就是通过异常断点发现是并发情况下user对象被清空了。普通调试可能要花几天用这个功能半小时就定位了。