Hi Peter,

we fixed that already (in Elasticsearch and Apache Solr): https://goo.gl/st9mm7 
(variant of Apache Solr)

The issue is: you cannot "import" the sun.management bean into your source 
code, because this makes it fail to compile with other non-Oracle/OpenJDK JVMs, 
like IBM's J9 or Android. So we need reflection here.
But what you can do is: use Class#forName() to look up the sun.management bean 
interface class and then reflect on that one. As the interface is public and 
exported, this works without setAccessible. You then just need to cast the 
OperatingSystemMXBean to that interface and invoke the previously reflected 
"public" interface method. This is what the above patch does.

Uwe

P.S.: This is why we use the "forbidden-apis" Maven/Ant/Gradle plugin to detect 
stuff like using non-standardized or unsafe APIs: 
https://github.com/policeman-tools/forbidden-apis ; this tool will fail your 
build whenever you use methods wich are not part of the Standard JDK. You can 
also forbid methods like String#toLowerCase(), because its locale dependent... 
You will not find any use of String#toLowerCase() without an explicit Locale 
anywhere in Lucene/Solr/Elasticsearch source code.

-----
Uwe Schindler
uschind...@apache.org 
ASF Member, Apache Lucene PMC / Committer
Bremen, Germany
http://lucene.apache.org/
> -----Original Message-----
> From: jigsaw-dev [mailto:jigsaw-dev-boun...@openjdk.java.net] On Behalf
> Of Peter Levart
> Sent: Saturday, September 12, 2015 12:27 PM
> To: Robert Muir; Alan Bateman
> Cc: jigsaw-dev@openjdk.java.net
> Subject: Re: Jigsaw EA feedback for elasticsearch
> 
> 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/Ref
> lection.java:462)
> >      at
> java.lang.reflect.AccessibleObject.checkCanSetAccessible(java.base@9.0/Ac
> cessibleObject.java:194)
> >      at
> java.lang.reflect.AccessibleObject.setAccessible(java.base@9.0/AccessibleO
> bject.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

Reply via email to