Hi, I recently looked for an easy way to get the CPU time spent by JIT-compiler and GC threads in Java (e.g exported by IBM J9's JvmCpuMonitorMXBean [0]). An easy way to achieve this is in OpenJDK is by using the "sun.management.HotspotInternal" MBean which exports the "sun.management:type=HotspotThreading" MBean with the attributes InternalThreadCount/InternalThreadCpuTimes (among other useful HotSpot internal counters and metrics).
Up until JDK 16/17 the usage of the "sun.management.HotspotInternal" MBean was straightforward, although it resulted in an illegal reflective access warning since JDK 9. Since JDK 17 its usage requires the " --add-exports java.management/sun.management=ALL-UNNAMED" for the monitored JVM. I wonder why "sun.management" was encapsulated in the first place? I understand that it is not an "officially supported" API, but I find it still quite useful. If we really don't want to export it, I wonder why we are maintaining it at all (we even have JTreg tests for it under "test/jdk/sun/management"), because in the current configuration it isn't particularly useful. Notice that jconsole supports the "sun.management.HotspotInternal" MBean if started with "J-Djconsole.showUnsupported=true" and the "java.management" module kind of tries to support jconsole with the following exports: exports sun.management to jdk.jconsole, jdk.management, jdk.management.agent; However, that doesn't help even if jconsole monitors itself (for the general case, where jconsole monitors a different JVM process it can't work anyway). With JDK 16 and "--illegal-access=debug" we can see why: WARNING: Illegal reflective access by sun.reflect.misc.Trampoline to method sun.management.HotspotThreadMBean.getInternalThreadCount() at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71) at java.base/sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:260) at java.management/com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(StandardMBeanIntrospector.java:112) at java.management/com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(StandardMBeanIntrospector.java:46) at java.management/com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(MBeanIntrospector.java:237) at java.management/com.sun.jmx.mbeanserver.PerInterface.getAttribute(PerInterface.java:83) at java.management/com.sun.jmx.mbeanserver.MBeanSupport.getAttribute(MBeanSupport.java:206) at java.management/com.sun.jmx.mbeanserver.MBeanSupport.getAttributes(MBeanSupport.java:213) at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttributes(DefaultMBeanServerInterceptor.java:701) at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.getAttributes(JmxMBeanServer.java:705) Notice that 'sun.reflect.misc.Trampoline' is loaded by a custom class loader ('java.base/sun.reflect.misc.MethodUtil') and not considered part of the base module. So to cut a long story short, I see several options: 1. Publicly export sun.management and restore the JDK 8 (or pre JDK 16) behavior. This would certainly require some polishing (e.g. some of the corresponding JVM functionality has already been removed [1]) but I think it could still be quite useful. 2. Port the useful functionality from the "sun.management" MBeans to corresponding "com.sun.management" MBeans and remove the "sun.management" MBeans. 3. Remove the "sun.management" MBeans without substitution. What do you think? Thank you and best regards, Volker [0] https://www.ibm.com/docs/en/sdk-java-technology/8?topic=interfaces-language-management [1] https://bugs.openjdk.org/browse/JDK-8134607