Using NetBeans Profiler to Hunt and Fix a Swing Memory Leak
Detect and fix memory leaks in Swing apps with NetBeans Profiler: set up allocation tracking, capture snapshots, compare results, and integrate the process into CI.
14 Aug 2026, 14:04 UTC

Problem: Hidden Memory Leaks in Long‑Running Swing Apps
Many desktop Java developers notice that a Swing application gradually slows down or eventually crashes after hours of use. The root cause is often an unnoticed memory leak—objects that are still reachable but no longer needed. Traditional debugging can be slow: you have to sift through stack traces, inspect object graphs, and guess which code path is leaking.
Thesis: NetBeans Profiler Gives You a Low‑Overhead, Point‑and‑Click Path to the Leak
The NetBeans Profiler (bundled since NetBeans 8.2) lets you capture heap snapshots, track live allocations, and compare memory usage over time, all from within the IDE. It is especially useful for Swing because the UI thread is the main consumer of memory, and the profiler integrates cleanly with the GUI event loop.
Setting Up the Profiler for a Swing Project
- Open the project in NetBeans 12.x or later, with JDK 11+.
- Choose
Profile > Profile Project. The Profiler Configuration dialog appears. - Under Memory select Snapshot and check Track object allocations.
- In Filters, add your application package (e.g.,
com.example.myapp) and excludeorg.netbeansto reduce noise. - Click
Start Profile. The application launches in a separate process.
During profiling you can interact with the UI, trigger actions, and watch the Heap view update in real time. When you think a leak might be present, click Take Snapshot to capture the current heap state.
Worked Example: A Static List Retaining JPanels
Below is a minimal Swing demo that unintentionally keeps a static List<JPanel> alive. Each time the user clicks a button, a new panel is created and added to the list, but the list is never cleared.
package com.example.swingleak;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class LeakDemo extends JFrame {
private static final List<JPanel> panels = new ArrayList<>();
public LeakDemo() {
setTitle("Swing Leak Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300, 200);
JButton btn = new JButton("Add Panel");
btn.addActionListener(e -> addPanel());
add(btn, BorderLayout.NORTH);
}
private void addPanel() {
JPanel p = new JPanel();
p.setBorder(BorderFactory.createLineBorder(Color.BLUE));
panels.add(p); // Leak source
getContentPane().add(p, BorderLayout.CENTER);
revalidate();
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new LeakDemo().setVisible(true);
});
}
}
Run the profiler, take a baseline snapshot (snapshot1), click the button a few times, and take a second snapshot (snapshot2).
In the Compare view, expand javax.swing.JPanel and see a delta of +N instances. The allocation path will point to com.example.swingleak.LeakDemo.panels, revealing the static list as the culprit.
Trade‑Offs and Limitations
- Runtime Overhead: Allocation tracking adds CPU load and can increase memory consumption, especially in UI‑heavy loops. Use short profiling sessions (30–60 s) and avoid running on a production machine.
- Profiler UI Variations: The exact menu names and filter settings may differ between NetBeans releases. The workflow above assumes NetBeans 12.x.
- CLI Availability: The command‑line interface (
profilerexecutable) requires the NetBeans Launcher module. Verify thatnbm:profileris installed before invoking CLI commands.
Actionable Closing: CI‑Based Leak Detection
To catch leaks before they reach users, add a lightweight profiling step to your nightly build:
# In your build script (e.g., Gradle or Maven)
nbmProfiler --snapshot --dir ./profiler-output
# After build, open the .nps file in NetBeans and check the "Memory" tab
# If the number of retained Swing components exceeds a threshold, fail the build
Set a threshold (e.g., maxPanels=50) and parse the snapshot using the nbm-profiler-export tool. Any upward trend triggers a review of static references or caching logic.
By integrating the Profiler into your workflow, you turn an opaque performance issue into a reproducible, data‑driven problem that can be fixed quickly.
Conclusion
NetBeans Profiler turns memory leak hunting from a guesswork exercise into a precise, visual investigation. While it introduces some overhead, the payoff—early detection, clear allocation paths, and actionable metrics—justifies its use for Swing applications that need to remain responsive over long periods.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.