Featured resource
2026 Tech Forecast
2026 Tech Forecast

Stay ahead of what’s next in tech with predictions from 1,500+ business leaders, insiders, and Pluralsight Authors.

Get these insights
  • Lab
    • Libraries: If you want this lab, consider one of these libraries.
    • Core Tech
Labs

Guided: Profiling and Diagnosing Java SE Applications

In this Code Lab, you will use standard JDK profiling and diagnostic tools to monitor performance and troubleshoot issues in a Java application. You will identify and fix a CPU bottleneck and a memory leak.

Lab platform
Lab Info
Level
Intermediate
Last updated
Dec 16, 2025
Duration
45m

Contact sales

By clicking submit, you agree to our Privacy Policy and Terms of Use, and consent to receive marketing emails from Pluralsight.
Table of Contents
  1. Challenge

    Introduction and Setup

    Welcome to the Guided Code Lab on Profiling and Diagnosing Java SE Applications!

    In this lab, you'll act as a performance engineer tasked with fixing a slow and memory-hungry Java application. You will use standard, powerful tools that come with the JDK to find and fix the root causes of these problems.

    The Scenario

    The DataProcessor application continuously loads and processes batches of customer data. However, it contains two common but critical bugs:

    1. A CPU bottleneck that makes the application unnecessarily slow.
    2. A memory leak that causes its memory footprint to grow indefinitely, leading to an eventual crash.

    Your Goal

    Your goal is to use profiling tools to understand the application's behavior, identify the faulty code, and implement fixes to make the application both fast and stable. You will be guided on how to use tools like Java VisualVM to analyze CPU, memory, and threads.

    info> This lab experience was developed by the Pluralsight team using Forge, an internally developed AI tool utilizing Gemini technology. All sections were verified by human experts for accuracy prior to publication. For issue reporting, please contact us.

  2. Challenge

    Step 2: Baseline Profiling and Initial Analysis

    Before you can fix anything, you need to understand the problem. The first step is to compile and run the application to observe its current, problematic behavior. You will also add some basic logging to get a rough idea of what's happening with the application's memory.

    After compiling, you would typically run the application and connect a profiler like VisualVM. You'd notice two things right away:

    1. The CPU usage is very high.
    2. The memory usage, as reported by your logging, steadily increases and never goes down.
  3. Challenge

    Step 3: Analyze and Fix the CPU Bottleneck

    Running a CPU profiler (like the Sampler in VisualVM) on the application would quickly reveal that a significant amount of time is spent in the DataProcessor.generateReport method. This is what's known as a 'hotspot'.

    Looking at the code, the cause is the use of the += operator to concatenate strings in a loop. In Java, strings are immutable. This means that each time you use +=, a new string object is created in memory, and the contents of the old and new parts are copied over. Doing this repeatedly in a loop is extremely inefficient.

    The standard solution is to use StringBuilder, which is a mutable sequence of characters designed specifically for this scenario.

  4. Challenge

    Step 4: Diagnose and Fix the Memory Leak

    Now that the CPU is no longer maxed out, the memory issue becomes more prominent. If you were to watch the application's heap in VisualVM's Monitor tab, you'd see the 'Used heap' size grow in a sawtooth pattern, but the bottom of the 'teeth' would constantly rise. This indicates that objects are surviving garbage collection—a classic sign of a memory leak.

    A heap dump analysis would show that millions of com.example.Customer objects are being kept alive by a static list: CUSTOMER_CACHE. The application adds customers to this cache in every cycle but never removes them. The garbage collector cannot reclaim the memory from these objects because a static variable holds a permanent reference to them.

    Your task is to fix this by clearing the cache after the objects inside it are no longer needed.

  5. Challenge

    Step 5: Investigate Thread Behavior

    The final area of diagnostics is thread analysis. Unresponsive applications are often caused by threads that are deadlocked or stuck waiting for a resource indefinitely. You can investigate this by taking a thread dump.

    A thread dump is a snapshot of the state of all threads in the JVM. Each thread will be in a specific state, such as:

    • RUNNABLE: The thread is actively executing code.
    • BLOCKED: The thread is waiting to acquire a lock.
    • WAITING / TIMED_WAITING: The thread is waiting for another thread or a specific amount of time.

    To practice this, you will add a method that simulates a blocking operation, which will cause the main thread to enter a TIMED_WAITING state. You could then use a tool like jcmd <pid> Thread.print or VisualVM's Threads tab to see this in action.

  6. Challenge

    Conclusion

    Congratulations on completing the lab!

    You have successfully diagnosed and fixed major performance and stability issues in a Java application. You have learned how to:

    1. Capture CPU, memory, and thread metrics: You added logging for memory and learned where to look in profiling tools for key metrics.
    2. Diagnose memory leaks and performance bottlenecks: You used conceptual profiling data to identify a CPU hotspot (String concatenation) and a memory leak (a static collection that is never cleared).
    3. Apply profiling data to improve application health: You refactored the inefficient code and patched the leak, resulting in a fast and stable application.

    These skills are fundamental for any professional Java developer responsible for building and maintaining robust, high-performance systems.

About the author

Pluralsight Code Labs offer an opportunity to get hands-on learning in real-time. Be it a Challenge, Sandbox, or Guided Lab, these provide the real world experience needed to succeed in your development role.

Real skill practice before real-world application

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Learn by doing

Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.

Follow your guide

All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.

Turn time into mastery

On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.

Get started with Pluralsight