-
Bug
-
Resolution: Fixed
-
Major
-
(JVM vendor still TBD)
A user of the Monitoring plugin reports seeing a repeated exception in the log:
java.lang.NoClassDefFoundError: com/sun/management/OperatingSystemMXBean at net.bull.javamelody.MemoryInformations.<init>(MemoryInformations.java:75) [javamelody-core-1.36.0.jar:1.36.0] at net.bull.javamelody.JavaInformations.<init>(JavaInformations.java:137) [javamelody-core-1.36.0.jar:1.36.0] at net.bull.javamelody.RemoteCallHelper$1.call(RemoteCallHelper.java:44) [:1.36.0] at net.bull.javamelody.RemoteCallHelper$1.call(RemoteCallHelper.java:36) [:1.36.0] at net.bull.javamelody.RemoteCallHelper$DelegatingTask.call(RemoteCallHelper.java:129) [:1.36.0] at hudson.remoting.LocalChannel$1.call(LocalChannel.java:52) [remoting-2.11.jar:]
Seems that operatingSystem was a com.sun.management.UnixOperatingSystem yet the JavaMelody code is not permitted to directly refer to com.sun.management.OperatingSystemMXBean.
Indeed making static reference to classes outside of the packages defined by the JRE is not safe; it will definitely fail for example in a default OSGi environment, and Java vendors are free to restrict access to such packages. Such code must be written defensively by using reflection and recovering gracefully from any errors.
By the way the isSunOsMBean checks for a class named com.sun.management.OperatingSystem but none such exists that I can see; was com.sun.management.OperatingSystemImpl meant?
Would be better to use reflection to try loading com.sun.management.OperatingSystemMXBean from the same class loader as operatingSystem, check if the bean is assignable to this interface, and if so look up methods such as getProcessCpuTime on that interface and call them on the bean. (Alternately, do all this with static classes but in a separate method wrapped in a try-block catching LinkageError.) Then there is no need to hardcode the implementation class names, which is even less stable than the com.sun.management package as a whole.