Hi Robert,
On 09/11/2015 10:58 PM, Robert Muir wrote:
On Fri, Sep 11, 2015 at 6:09 AM, Alan Bateman <alan.bate...@oracle.com> wrote:
I'm not sure that I understand the issue here but just to say that the
com.sun.management API is a documented/supported API and it exported by
module jdk.management:
$ java -listmods:jdk.management
jdk.management@9.0
requires public java.management
requires mandated java.base
exports com.sun.management
conceals com.sun.management.internal
provides sun.management.spi.PlatformMBeanProvider with
com.sun.management.internal.PlatformMBeanProviderImpl
Here is code that fails:
import java.lang.reflect.*;
import java.lang.management.*;
public class test {
public static void main(String args[]) throws Exception {
OperatingSystemMXBean osMxBean =
ManagementFactory.getOperatingSystemMXBean();
Method getTotalPhysicalMemorySize =
osMxBean.getClass().getMethod("getTotalPhysicalMemorySize");
getTotalPhysicalMemorySize.setAccessible(true);
System.out.println(getTotalPhysicalMemorySize.invoke(osMxBean));
}
}
Exception in thread "main"
java.lang.reflect.InaccessibleObjectException: Unable to make member
of class com.sun.management.internal.OperatingSystemImpl accessible:
module jdk.management does not export com.sun.management.internal to
<unnamed module @5f375618>
at
sun.reflect.Reflection.throwInaccessibleObjectException(java.base@9.0/Reflection.java:462)
at
java.lang.reflect.AccessibleObject.checkCanSetAccessible(java.base@9.0/AccessibleObject.java:194)
at
java.lang.reflect.AccessibleObject.setAccessible(java.base@9.0/AccessibleObject.java:157)
at test.main(test.java:8)
I guess there will be lots of similar issues discovered in various
codebases when trying to run them with jigsaw. The problem of the above
code is that it uses reflection to look up the optional method on the
implementation class of the object (and that class is in some internal
package, not exported and inaccessible to other modules) instead of
looking it up on the public API class (the interface). You get two
different methods that way - one is accessible and the other is not, but
invoking either of them should be equivalent, since the dispatch is
always virtual. So the correct way to "test" whether the method exists
(maybe because it has been added on a praticular version of the
platform) and then to invoke it is the following:
public class test {
public static void main(String args[]) throws Exception {
Method getTotalPhysicalMemorySize =
OperatingSystemMXBean.class.getMethod("getTotalPhysicalMemorySize");
OperatingSystemMXBean osMxBean =
ManagementFactory.getOperatingSystemMXBean();
System.out.println(getTotalPhysicalMemorySize.invoke(osMxBean));
}
}
And you don't even need to set it Method.setAccessible(true), since both
the interface and method are public.
Regards, Peter