Using NetBeans to analyse Java memory with VisualVM

A Java application can appear healthy in NetBeans while quietly consuming more heap after every request. Memory leaks, oversized caches and excessive temporary objects often reveal themselves only when the program runs under a realistic workload. VisualVM provides a practical way to inspect those behaviours while NetBeans remains the place for editing, building and controlling the development cycle.

The tools complement each other. NetBeans helps you start the application with predictable options, select the right Maven or Gradle project and reproduce a suspected problem. VisualVM then displays heap consumption, garbage collection activity, thread states, classes and snapshots that can be compared over time.

This workflow suits Australian development teams working across Sydney, Melbourne, Brisbane and Perth, where a laptop test may run in a different time zone from a hosted service. A memory pattern seen at 4 pm AEST can be very different from one produced during an overnight batch job or a Boxing Day retail rush.

VisualVM is distributed separately from current JDK releases, so install a compatible version before beginning. Keep the Java versions reasonably aligned, particularly when diagnosing a service that runs in a container or on a managed cloud platform. A short “no worries” setup is useful, but reliable results still depend on repeatable tests.

Preparing NetBeans and VisualVM

Start the application from NetBeans using the same configuration that exposes the issue. Record the JDK version, maximum heap, garbage collector and important system properties. Maven and Gradle projects may use different run profiles, so verify that the IDE is launching the intended module rather than a convenient default.

Open VisualVM and look under Local for the Java process. If it does not appear, check that VisualVM has permission to inspect the process and that both tools use compatible Java installations. A process launched with elevated privileges may also be invisible to a normally running VisualVM instance.

The NetBeans ecosystem includes many project-specific references, and the site’s NetBeans categories can help locate related material on IDE configuration, Java EE and application-server development. This is especially useful when memory growth occurs inside an EJB, web module or scheduled service rather than in a small desktop program.

Reading the main VisualVM views

The Monitor tab gives an immediate overview of heap usage, used metaspace, loaded classes and active threads. A healthy application usually shows saw-tooth heap behaviour: usage rises, garbage collection runs, and the used level falls. A steadily rising baseline after full collections is a stronger leak signal than a high but stable peak.

The Sampler tab separates memory by class and can show which object types dominate the heap. Take an initial snapshot, exercise one business operation repeatedly, then take another. Comparing the counts and sizes of objects such as byte arrays, session objects, collections or ORM entities can narrow the investigation.

The Profiler offers deeper detail but adds overhead, so it should be used carefully. Sampling is usually a sensible first step for a running service, while instrumentation can provide more exact allocation information during a controlled test. For a production-like environment, begin with monitoring and a heap dump rather than attaching a heavy profiler during a busy period.

Capturing evidence without distorting results

A heap dump records objects and references at a particular moment. Capture one after startup and another after the suspected workflow has been repeated and garbage collection has had an opportunity to run. Comparing retained sizes can reveal a collection, cache or listener that still holds objects which should have been released.

Use a representative data set. A Melbourne developer testing ten records on a workstation will not reproduce the same pressure as a Sydney service processing thousands of customer events. Australian organisations also need to consider privacy obligations: heap dumps may contain names, email addresses, access tokens or payment-related values, so store them securely and remove them when analysis is finished.

For remote instances, enable the appropriate JMX configuration and protect the connection with authentication, encryption and network restrictions. Do not expose a management port directly to the public internet. When a service is running on a separate host, the remote Java debugging guide provides useful background on connecting development tools to remote applications.

A practical workflow for Australian teams

A repeatable sequence prevents a vague complaint such as “the app gets sluggish in the arvo” from becoming an inconclusive investigation. Keep a small record of the test date, JVM settings, application version, workload and time zone. That detail matters when comparing a local result with an AEST or AWST production incident.

Use these checks before drawing a conclusion:

  • Start with a clean JVM and record the initial heap and thread counts.
  • Run one business scenario repeatedly with a fixed data set.
  • Force or wait for garbage collection only when the test procedure permits it.
  • Capture VisualVM screenshots, sampler results and heap dumps at matching points.
  • Compare retained objects rather than relying on total allocated bytes.
  • Repeat the test after changing one setting or code path.

A memory graph alone does not prove a leak. Caches may be deliberately bounded, and the JVM can retain committed memory after objects have been collected. Review the application’s cache policy and allocation rate before changing the heap size. Libraries such as Ehcache deserve particular attention; discussion of Ehcache L2 caching illustrates why cache configuration can influence both performance and memory use.

When the evidence points to a cache, inspect eviction limits, expiry times and key construction. When it points to threads, check executor shutdown and request context cleanup. When it points to class loaders, look for redeployment behaviour and unmanaged resources.

Turning findings into a safe fix

After identifying the retaining path, reproduce the issue in a small test where possible. A heap dump can show that a map retains thousands of objects, but the code review must explain why those entries remain reachable. Common causes include static collections, unclosed resources, listeners that are never deregistered and thread-local values surviving longer than expected.

Change one variable at a time, then run the same workload and compare snapshots. Increasing -Xmx may delay an outage while masking the defect, whereas reducing an unbounded cache or closing a resource addresses the cause. GC logs and application metrics should support VisualVM rather than replace it.

For teams hiring Java contractors or comparing local expertise, a technical portfolio such as Phil Schwartz’s work can provide useful context on JVM and software engineering experience. The practical standard remains the same: document the evidence, protect diagnostic data and verify the fix under realistic load.

NetBeans and VisualVM form an effective pairing because each tool has a clear role. NetBeans manages the source, build and launch process; VisualVM turns JVM behaviour into observable evidence. With disciplined snapshots, secure remote access and workloads that resemble Australian production conditions, memory investigations become a measured engineering task rather than a late-night guess.