Java Profiling Tools: Beyond JProfiler (2025)

Java profiling tools help identify performance bottlenecks and optimize applications. This comprehensive guide explores various profiling tools and techniques beyond JProfiler.
Pro Tip: Profiling tools help identify performance bottlenecks and memory issues in Java applications.
Table of Contents
Async Profiler
Note: Async Profiler provides low-overhead profiling capabilities.
Async Profiler Configuration
# Download and install Async Profiler
wget https://github.com/jvm-profiling-tools/async-profiler/releases/download/v2.9/async-profiler-2.9-linux-x64.tar.gz
tar xzf async-profiler-2.9-linux-x64.tar.gz
# Start profiling with CPU sampling
./profiler.sh -d 30 -f cpu-profile.svg 12345
# Start profiling with memory allocation
./profiler.sh -d 30 -e alloc -f alloc-profile.svg 12345
# Start profiling with lock contention
./profiler.sh -d 30 -e lock -f lock-profile.svg 12345
Async Profiler Integration
public class AsyncProfilerExample {
public static void main(String[] args) {
// Start profiling
AsyncProfiler.getInstance().start("cpu");
// Your application code
processData();
// Stop profiling and get results
String result = AsyncProfiler.getInstance().stop();
System.out.println(result);
}
private static void processData() {
// Simulate CPU-intensive work
for (int i = 0; i < 1000000; i++) {
Math.sqrt(i);
}
}
}
Java Flight Recorder
Pro Tip: Java Flight Recorder provides detailed event-based profiling.
JFR Configuration
// Enable JFR at startup
java -XX:StartFlightRecording=duration=60s,filename=recording.jfr -jar app.jar
// Start JFR programmatically
public class JFRExample {
public static void main(String[] args) {
// Configure recording settings
RecordingSettings settings = new RecordingSettings();
settings.setDuration(Duration.ofSeconds(60));
settings.setFilename("recording.jfr");
// Start recording
FlightRecorder.getFlightRecorder().startRecording(settings);
// Your application code
processData();
// Stop recording
FlightRecorder.getFlightRecorder().stopRecording();
}
}
Custom Events
@Label("Order Processing")
@Description("Records order processing events")
public class OrderEvent extends Event {
@Label("Order ID")
private String orderId;
@Label("Processing Time")
private long processingTime;
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public void setProcessingTime(long processingTime) {
this.processingTime = processingTime;
}
}
public class OrderProcessor {
public void processOrder(Order order) {
OrderEvent event = new OrderEvent();
event.begin();
try {
// Process order
processOrderLogic(order);
event.setOrderId(order.getId());
event.setProcessingTime(System.currentTimeMillis() - event.getStartTime());
} finally {
event.commit();
}
}
}
Java Mission Control
Note: Java Mission Control provides advanced analysis of JFR recordings.
JMC Analysis
// Configure JMC for analysis
public class JMCAnalysis {
public static void main(String[] args) {
// Enable detailed GC logging
System.setProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager");
System.setProperty("java.util.logging.config.file", "logging.properties");
// Configure GC options
System.setProperty("java.awt.headless", "true");
System.setProperty("sun.rmi.dgc.server.gcInterval", "3600000");
// Your application code
processData();
}
}
GC Analysis
public class GCAnalysis {
public static void main(String[] args) {
// Configure GC logging
System.setProperty("java.util.logging.config.file", "gc-logging.properties");
// Enable GC events in JFR
System.setProperty("jdk.jfr.event.gc.enabled", "true");
// Your application code
processData();
}
}
VisualVM
Pro Tip: VisualVM provides comprehensive monitoring and profiling capabilities.
VisualVM Integration
public class VisualVMExample {
public static void main(String[] args) {
// Enable JMX
System.setProperty("com.sun.management.jmxremote", "true");
System.setProperty("com.sun.management.jmxremote.port", "9999");
System.setProperty("com.sun.management.jmxremote.authenticate", "false");
System.setProperty("com.sun.management.jmxremote.ssl", "false");
// Enable VisualVM profiler
System.setProperty("visualvm.display.name", "My Application");
// Your application code
processData();
}
}
Custom Monitoring
@MXBean
public interface CustomMetricsMXBean {
@Description("Get current order count")
int getOrderCount();
@Description("Get average processing time")
double getAverageProcessingTime();
}
public class CustomMetrics implements CustomMetricsMXBean {
private int orderCount = 0;
private long totalProcessingTime = 0;
@Override
public int getOrderCount() {
return orderCount;
}
@Override
public double getAverageProcessingTime() {
return orderCount > 0 ? (double) totalProcessingTime / orderCount : 0;
}
public void recordOrder(long processingTime) {
orderCount++;
totalProcessingTime += processingTime;
}
}
Best Practices
Note: Following profiling best practices ensures accurate results.
Profiling Best Practices
- Profile in production-like environment
- Use appropriate sampling rates
- Monitor overhead impact
- Use proper event thresholds
- Analyze both CPU and memory
- Use proper recording duration
- Enable relevant events
- Use proper analysis tools
- Monitor system resources
- Use proper logging levels
- Enable thread profiling
- Use proper GC settings
- Enable proper security
- Use proper data collection
- Follow profiling guidelines
Conclusion
Java profiling tools provide powerful capabilities for performance analysis and optimization. By understanding and utilizing these tools effectively, you can identify and resolve performance issues in your applications.