Overview

3 Finding problem root causes using advanced debugging techniques

This chapter expands beyond basic step-into/over/out navigation to show how modern debuggers can drastically reduce investigation time and help you reach root causes faster. It emphasizes using the right tool for the right scenario, balancing speed with accuracy, and being mindful of trade-offs and IDE differences. Through practical examples, it demonstrates when advanced techniques accelerate understanding and when they can mislead or slow you down, especially in complex or long-running flows.

The first set of techniques centers on conditional breakpoints and non-suspending (log-only) breakpoints. Conditional breakpoints pause execution only when a boolean condition is met, letting you jump straight to interesting states (for example, when a variable equals an unexpected value), though they can slow execution due to constant condition evaluation. Non-suspending breakpoints log values and stack traces without halting the program, giving you lightweight, code-free observability you can combine with conventional logging. The chapter also highlights tool support differences (some IDEs lack log-only breakpoints) and shows how AI assistants can suggest breakpoint placement or conditions and help analyze large logs—useful for speed—but advises relying on your own judgment rather than outsourcing reasoning to AI.

The second set of techniques enables you to shape the scenario mid-flight. Modifying in-memory variables while paused helps simulate hard-to-reproduce cases or avoid waiting on lengthy processes, with caveats around immutability (for example, final fields and records). The chapter then explains “dropping frames,” which rewinds one call-stack layer so you can re-run a method—distinct from stepping out, which fast-forwards to the caller after completion. This is powerful for rechecking a sequence but is not an undo: any external side effects (database writes, filesystem changes, messages sent, calls to other services) persist and can make repetitions diverge or fail. The guidance is to use these tools deliberately, repeat small blocks when safe, and remain alert to external effects that can invalidate a replayed path.

Using a conditional breakpoint to pause the execution just for specific cases. In this figure, we want to pause the execution on line 14 only if sum is zero. We can apply a condition on the breakpoint that instructs the debugger to consider that breakpoint only if the given state is true. This helps you more quickly get to a scenario you want to investigate.
A conditional breakpoint. Line 14 in the figure was executed multiple times, but the debugger only paused the execution when the variable sum was zero. This way, we skipped over all the cases we were not interested in so that we can start with the conditions relevant to our investigation.
AI assistants like GitHub Copilot can help you better understand a code snippet or assist in selecting the appropriate troubleshooting technique. In this example, I asked Copilot for guidance on where to place breakpoints to easily identify the source of the issue in my code.
You can speed up your investigation by asking your AI assistant to suggest the lines of code for adding conditional breakpoints and the right condition to use for them.
Tools like ChatGPT, Gemini, or similar AI-powered chatbots can also assist with your code investigation. In some cases, if they have enough context, they may even provide a complete solution.
To apply advanced configuration on the breakpoint in IntelliJ, you can click the More button.
Not all IDEs offer the same debugging tools. All IDEs give you the basic operations, but some features, such as logging the execution details instead of pausing the execution, may be missing. In Eclipse, you can define conditional breakpoints, but you can’t use the logging feature.
Conditional breakpoint advanced configuration. In addition to specifying a condition for the breakpoint, you can instruct the debugger to not suspend the execution for the given breakpoint. Instead, you can simply log the data you need to understand your case.
Using breakpoints without pausing the execution. Instead, the debugger logs a message when the line has been reached. The debugger also logs the value of the digits variable and the execution stack trace.
Usually, when investigating issues in a long-running process, using breakpoints is not really an option. It can take a long time for the execution to reach the part of code you are investigating, and if you have to rerun the process several times, you will definitely spend too much time on it.
Setting a new value in a variable in scope. The debugger shows you the values for the variables in scope when it pauses the execution on a given line. You can also change the values to create a new investigation case. In some cases, this approach can help you to validate your suspicions about what the code does.
Change the variable's value to observe how the app’s execution behaves in different conditions.
When using the step over operation, the app uses the new value you set to the s variable. extractDigits() returns an empty list because string "abcd" doesn’t contain digits. Setting values in variables on the fly allows you to test different scenarios even if you don’t have the input data you need.
Stepping out closes the current investigation plan by executing the method and then pausing the execution right after the method call. This operation allows you to continue the execution and return one layer in the execution stack.
When you drop a frame, you return to the previous layer in the execution stack trace before the method call. This way, you can replay the method execution either by stepping into it again or stepping over it.
Dropping a frame versus stepping out. When you drop a frame, you return to the line before the method’s execution. When you step out, you continue the execution but close the current investigation plan (represented by the current layer in the execution stack).
When using IntelliJ IDEA, you can drop a frame by right-clicking the method’s layer in the execution stack trace and then selecting Drop Frame.
Using the drop frame operation can result in some events that can’t be undone. Examples include changing data in the database, changing data in the filesystem, calling another app, or sending an email message.

Summary

  • A conditional breakpoint is a breakpoint associated with a Boolean condition. The debugger pauses the execution only if the provided condition is true—that is, only when particular conditions apply. This way, you save the time of navigating through code until you get to the desired point to begin your investigation.
  • You can use breakpoints to log the values of certain variables in the console that don’t suspend the app’s execution. This approach is quite helpful because you can add log messages without changing the code.
  • Moreover, you can use AI assistants to analyze large amounts of log messages to discover anomalies and guide your next steps in the troubleshooting process.
  • When the debugger pauses the execution on specific lines of code, you can alter the data on the fly to create custom scenarios according to what you want to investigate. This way, you don’t have to wait until the execution gets to a conditional breakpoint. In some cases, when you don’t have an appropriate environment, changing data while debugging saves you time you would have needed to prepare the data in the environment.
  • Changing variables’ values to create a custom investigation scenario can be an efficient technique when trying to understand just a piece of the logic of a long-running process or when you don’t have the desired data in the environment where you run the app. However, changing more than one or two variable values at a time may add considerable complexity and make your investigation more challenging.
  • You can step out of an investigation plan and return to the point before the method was called. This is called dropping a frame, but it can sometimes introduce an unwanted side effect. If the app changed anything externally (e.g., committed a transaction and changed some database records, changed a file in the filesystem, or made a RESTful call to another app), returning to a previous execution step won’t undo these changes.

FAQ

What is a conditional breakpoint, and why would I use it?A conditional breakpoint pauses execution only when a boolean expression you define evaluates to true (for example, sum == 0). It helps you skip irrelevant iterations or cases and jump straight to the scenario you want to investigate, saving time compared to manually stepping through code.
How do I set a conditional breakpoint in IntelliJ IDEA?Place a breakpoint, right-click it, and add a boolean condition in the breakpoint settings (e.g., sum == 0). The debugger will pause only when that condition holds.
Do conditional breakpoints affect performance?Yes. The debugger must evaluate the condition each time the line is hit, which can significantly slow down execution, especially in tight loops or frequently executed code.
What is a non-blocking (logging) breakpoint and when should I use it?A non-blocking breakpoint logs information (messages, variable values, stack traces) when hit without pausing the program. Use it to collect runtime evidence quickly without altering code or interrupting long-running processes.
Do all IDEs support logging breakpoints?No. IntelliJ IDEA supports breakpoints that only log without suspending. Eclipse supports conditional breakpoints but does not offer logging-only breakpoints.
When should I modify variable values on the fly instead of using conditional breakpoints?Prefer on-the-fly value changes when the code takes a long time to reach the case you need or when you can’t reproduce the exact input (e.g., production-only issues). Use conditional breakpoints when you already have the triggering data and the code runs quickly.
How do I change variable values during debugging, and what are the limitations?While paused, right-click a variable in scope and set a new value that matches its type. Limitations: it’s practical only for a small number of changes; you can’t modify final/immutable data (e.g., record components in Java); and changing too many values becomes hard to manage.
What is “dropping a frame,” and how is it different from “stepping out”?Dropping a frame rewinds execution to the call site before the current method was invoked, letting you re-run that call. Stepping out runs the current method until it returns, then pauses after the call. Think of dropping a frame as rewind, stepping out as fast-forward.
What are the risks of dropping frames when code causes external side effects?Dropping a frame is not an undo. External side effects (DB writes, file changes, calling external services, sending messages/emails) persist. Replaying the code can yield different results or errors (e.g., file already exists), making investigations confusing.
How can AI assistants help with debugging, and what should I watch out for?AI tools can suggest breakpoint locations/conditions, summarize or compare logs, and highlight anomalous states (e.g., suggest sum < 0). Provide sufficient context (code, logs, line numbers) and treat AI as a helper, not a crutch—validate suggestions and beware of hallucinated answers.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Troubleshooting Java, Second Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Troubleshooting Java, Second Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Troubleshooting Java, Second Edition ebook for free