Overview

1 Starting to know your apps

Modern Java development demands strong troubleshooting skills because most of a developer’s time is spent understanding existing behavior rather than writing new code. The chapter frames troubleshooting as a disciplined investigation: observe how the system actually behaves, compare it to how it should behave, and isolate the differences. It broadens the notion of “debugging” beyond the debugger tool to the wider practice of code investigation used to fix bugs, extend features, learn unfamiliar codebases, improve performance, and harden security. Becoming effective at this work makes you faster, more confident, and more independent—and while AI can accelerate the process, it augments rather than replaces your judgment about domain rules, context, and subtle cues.

The chapter surveys practical techniques and typical scenarios. Reading code alone is often insufficient; a debugger helps step through hard-to-follow logic, but it isn’t always viable, especially in large systems or multithreaded code where interference can mask issues. Profilers reveal what actually executes and where time is spent, guiding where to place breakpoints or focus analysis, and are particularly useful for slowness (often I/O bound). Logging provides low-intrusion visibility and is essential when concurrency or timing-sensitive behavior produces Heisenbugs. For external integrations, stubs let you control and observe interactions to pinpoint faulty request construction. When systems crash or can’t be reproduced locally, postmortem investigation with logs, heap dumps, and thread dumps becomes critical for diagnosing memory leaks, deadlocks, and other production-only failures. Investigation is also a powerful way to learn complex frameworks like Spring Security or Hibernate by seeing their internals in action.

AI is presented as a game changer when used thoughtfully: describe the problem richly to get starting hypotheses, prefer prompts that explain code step by step, iterate on responses, and never paste sensitive data or accept answers uncritically. Beyond ideation, AI can help summarize logs and large data sets, but you remain the detective who validates leads and connects context. By the end, the book aims to equip you to choose the right technique for the situation—advanced debugger use, profiling hidden behavior, effective logging, and analyzing memory and thread snapshots—while leveraging AI to speed insight. These skills elevate both newcomers and experienced engineers by turning investigation into a deliberate, repeatable craft.

Code investigation is not only about finding problems in software. Today, apps are complex. We often use investigation techniques to understand an app’s behavior or simply to learn new technologies.
Investigating code doesn’t require much physical effort, but debugging sometimes makes you feel like Lara Croft or Indiana Jones. Many developers enjoy the unique sensation of solving the puzzle of a software issue.
Code investigation techniques. Depending on the case, a developer can choose from one or more of these techniques to understand how a certain capability works.
Using a debugger, you can pause the execution before a particular instruction and then observe how the app’s logic changes the data by manually running the instructions step by step.
Identifying code in execution with a profiler. If you don’t know where to start debugging, the profiler can help you to identify the code that is running and give you an idea of where you can use the debugger.
A Heisenberg execution. In a multithreaded app, when a debugger interferes with the app’s execution, it might change how the app behaves. This change doesn’t allow you to correctly investigate the initial app behavior that you wanted to research.
A wrong output can be your app sending erroneous requests to another system component. You may be asked to investigate such a behavior and find its root cause.
You can replace the system component your app calls with a stub. You control the stub to determine where your app sends the request from quickly. You can also use the stub to test your solution after you correct the issue.
Investigating slowness problems with a profiler. The profiler shows you the time spent on each instruction during code execution. This profiler feature is excellent for identifying the root causes of performance problems.
A heap dump is like a map of the heap memory. If you learn how to read it, it gives you invaluable clues about how the app internally processes data. A heap dump helps you investigate memory problems or performance issues. In this example, you can easily find which object fills most of the app’s memory and that the Product and String instances are related.
A thread dump provides details about the threads that were running when the dump was taken. It includes thread states and the stack traces, which tell you what the threads were executing or what blocked them. These details are valuable for investigating why an app is stuck or is having performance problems.

Summary

  • You can use various investigation techniques to analyze software behavior.
  • Depending on your situation, one investigation technique may work better than another. You need to know how to choose the correct approach to make your investigation more efficient. AI tools may prove extremely helpful to help you determine where to start from and what troubleshooting techniques to apply.
  • For some scenarios, using a combination of techniques helps you to identify a problem faster. Learning how each analyzing technique works gives you an excellent advantage in dealing with complex problems.
  • In many cases, developers use investigation techniques to learn new things rather than to solve problems. When learning complex frameworks such as Spring Security or Hibernate, simply reading books or the documentation isn’t enough. An excellent way to accelerate your learning is to debug examples that use a technology you want to better understand.
  • A situation is easier to investigate if you can reproduce it in an environment where you can study it. Reproducing a problem not only helps you find its root cause more easily, but it also helps you to confirm that a solution works when it is applied.

FAQ

What does “troubleshooting” mean in this chapter?Troubleshooting is the process of understanding how a system actually behaves, comparing it with how it should behave, and identifying the differences. It’s about structured investigation, not guesswork, and it applies whether you’re writing new code or fixing production issues.
Why is troubleshooting such an important skill for developers?Strong troubleshooting skills make you faster, more confident, and more independent. They help you work in unfamiliar codebases, solve production incidents, spot design flaws early, and generally spend less time stuck—because most time is spent understanding existing behavior, not typing new code.
How is “investigating code” different from “debugging,” and is a debugger the only tool?Investigating code means analyzing behavior for many purposes: finding root causes, learning a framework, extending features, reviewing correctness, improving performance, or security. A debugger is just one technique. Others include logging, profilers, heap dumps, thread dumps, and postmortem analysis—each suits different scenarios.
How do I approach a simple case of unexpected output?First clarify the expected output (e.g., console text, DB changes, HTTP response). Then use a debugger: set breakpoints where the output is produced, step through code, watch variable changes, and evaluate expressions to see where behavior diverges from expectations.
What if I don’t know where to start debugging?Use a profiler to see which code paths actually execute during the scenario. This narrows candidates for breakpoints and shows call trees and hot spots so you can focus your investigation where it matters.
How do I troubleshoot multithreaded behavior and avoid Heisenbugs?Stepping with a debugger can change timing and mask or create issues. Prefer techniques that minimize interference: add targeted logging, capture thread dumps, reduce concurrency to a single thread to reproduce deterministically, and use profilers cautiously.
How can I diagnose bad requests sent to another service?Identify where requests are built and sent. If that’s unclear, replace the external service with a controllable stub that can delay or capture requests. Use a profiler to find the code waiting on the stub, inspect how the request is constructed, fix it, and validate again against the stub.
What is postmortem investigation, and which artifacts should I collect?Postmortem investigation analyzes failures after the app has crashed or is unresponsive. Key artifacts include logs, the last known output, heap dumps (memory snapshots, great for OutOfMemoryError), and thread dumps (thread states and stack traces for stuck apps). These help you infer root causes without live debugging.
How do I approach performance problems, especially slowness?Profile the scenario to see where time is spent per method or call. Many slowdowns come from I/O (DB, filesystem, network). Use the profiler’s timing data to locate the true bottleneck, then optimize the specific call path rather than guessing broadly.
How can AI help in troubleshooting, and what are good prompt practices?AI can suggest starting points, summarize logs/stack traces, and explain code step by step. Best practices: be descriptive but avoid sensitive data, ask for step-by-step reasoning instead of just “what does this do,” treat outputs as guidance (verify them), and iterate with follow-up prompts to refine hypotheses.

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
$399.99
only $33.33 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
$399.99
only $33.33 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