When teams migrate from traditional classpath-based projects to the Java Platform Module System (JPMS), one of the overlooked areas is monitoring and diagnostics. Many developers assume tools like Java Flight Recorder (JFR) and Java Management Extensions (JMX) work seamlessly without modular considerations. The reality? Improperly configured modules often lead to errors like:
- “package not visible to JFR”
- “access denied to JMX MBeans”
For cloud-native and enterprise applications, monitoring is as critical as the application itself. Without proper observability, debugging performance issues or memory leaks in modular systems can become a nightmare. This is why understanding how JFR and JMX interact with modules is essential.
Think of JPMS modules like secure office departments. JFR is the security camera, and JMX is the management dashboard. Both need the right keys (exports/opens) to function without breaking encapsulation.
Monitoring with Java Flight Recorder (JFR)
What is JFR?
- Low-overhead profiling and event collection tool integrated into the JDK
- Records CPU usage, GC activity, thread contention, class loading, and more
Enabling JFR in Modular Apps
java --module-path mods --add-exports java.base/jdk.internal.perf=ALL-UNNAMED -XX:StartFlightRecording=filename=recording.jfr,duration=60s -m com.example.app/com.example.app.Main
Key Considerations
- Some internal JDK packages require
--add-exports
for JFR access - Recordings can be analyzed in Java Mission Control (JMC)
Monitoring with Java Management Extensions (JMX)
What is JMX?
- Framework for monitoring and managing Java applications
- Exposes MBeans for runtime inspection and operations
Enabling JMX in Modular Apps
java --module-path mods --add-opens com.example.app/com.example.app.monitoring=java.management -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.authenticate=false -m com.example.app/com.example.app.Main
Key Considerations
- Use
opens
or--add-opens
for reflective access to MBeans - Avoid exposing sensitive MBeans without authentication in production
Example: Modular Monitoring Setup
module-info.java
module com.example.app {
requires java.management; // for JMX
exports com.example.app.api;
opens com.example.app.monitoring to java.management; // reflective access
}
Main Class
package com.example.app.monitoring;
import javax.management.*;
import java.lang.management.ManagementFactory;
public class MonitoringAgent {
public static void registerMBean() throws Exception {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example:type=AppMonitor");
server.registerMBean(new AppMonitor(), name);
}
}
Pitfalls
❌ Forgetting to opens
packages → JMX access errors
❌ Using --add-exports
excessively → weakens modular encapsulation
❌ Ignoring security when enabling JMX remotely
❌ Mixing classpath and module path in monitoring agents
Best Practices
✅ Use explicit requires java.management
for JMX
✅ Export only monitoring-specific APIs
✅ Restrict JMX access with authentication in production
✅ Document runtime flags (--add-exports
, --add-opens
) in CI/CD pipelines
✅ Use JFR for low-overhead production profiling
What's New in Java Versions?
- Java 5–8 → N/A (no JPMS)
- Java 9 → JPMS introduced; JFR integrated into JDK (commercial feature before)
- Java 11 → JFR open-sourced, widely available
- Java 17 → Performance and stability improvements in JFR
- Java 21 → No significant updates across Java versions for this feature
Real-World Analogy
Monitoring modular applications is like installing CCTV cameras (JFR) and dashboards (JMX) in an office building. Without proper keys (exports
and opens
), the cameras and dashboards can’t access the right rooms. Once configured, they provide visibility without disrupting operations.
Summary & Key Takeaways
- JFR provides profiling and performance analysis for modular apps
- JMX exposes MBeans for runtime management and debugging
- Use
--add-exports
and--add-opens
carefully for monitoring needs - Always secure JMX connections in production
- Modular monitoring requires explicit configuration in
module-info.java
FAQ: Monitoring Modular Apps with JFR & JMX
1. What’s the difference between JFR and JMX?
JFR records runtime events, JMX exposes management interfaces.
2. Why do I get “package not visible” errors with JFR?
Because internal JDK packages need --add-exports
for access.
3. Why can’t my JMX MBeans be registered?
Because the package wasn’t opened
to java.management
.
4. Can I use JFR in production?
Yes, it’s low-overhead and designed for production use.
5. Is JMX safe for production use?
Yes, but enable authentication and SSL for remote access.
6. Do I need to modularize monitoring agents?
Yes, agents should declare proper requires
and opens
.
7. Does JPMS improve monitoring security?
Yes, by enforcing explicit exports and opens for monitoring packages.
8. Can I use ALL-UNNAMED
for quick fixes?
Yes, but it weakens modular security—avoid in production.
9. Do frameworks like Spring Boot support JFR and JMX with JPMS?
Yes, but they may need extra --add-opens
flags for reflection.
10. Do these flags affect jlink
custom runtimes?
Yes, you must include required modules and opens in your runtime image.