Using java.awt.Toolkit.getDefaultToolkit().getScreenSize() reflectively causes InaccessibleObjectException

Rony G. Flatscher Rony.Flatscher at wu.ac.at
Fri Jan 6 12:26:57 UTC 2017


Alan,

thank you for your pointer.

The code shown in [1] currently needs to access Java 9 features (to test whether the module is
exported), which might not be a possibility for Java libraries that have a baseline like Java 1.4
(the GA version of the Java bridge is at that level) or 1.6 (the current beta version of the Java
bridge raises the baseline to 1.6, which depends on the deployed Java runtimes; businesses hardly
update to a newer level for a proved and stable running application system, where Java developers
love to be on the latest version). 

However, before turning to possible implementations that circumvent the problem that gets introduced
by the current implementation of the Java 9 module system, the question would be first, whether such
breaking effects can be inhibited by changing the current implementation.

---

In my case it is possible to start to program around the problem one way or the other (maybe using
JNI, which would be some last resort, of course), because I have access to the sourcecode and I
would know the gory details of my own implementation.

This possibility is not necessarily available if businesses employ legacy, third party, complex or
closed Java libraries which break because of this. It may also not be possible to fix this current
incompatibility if (like a large) company rules inhibit replacing deployed and proven installations,
which would mean that deployment of Java 9 would be a problem there.

---

To turn back to the root cause: using reflection a public class from java.desktop is loaded, one of
its public static methods gets employed and returns an object of the type of that public
java.desktop class. Under the covers, however, an object gets returned which got instantiated by
that java.desktop class from a class that resides in a module that is open to java.desktop, but
closed to others.

This action is not under control of the reflective code, it is the sole responsibility of the
accessible public class' public method. Applying reflectiveness on that object, like it has been
possible for many Java versions and years in the past, all of a sudden breaks in this case with an
exception, that pre-Java-9 code could never have taken into account. The code does nothing unusual
and respects the publicness of classes and its public members.

So the current implementation of the module access rules to public (!) methods of the returned
object/in place of an accessible public class/ may break existing, proven, legitimate, reflective code.

Such established and tested Java reflective code can be expected to be hit quite a lot in the wild,
beating Java applications that might all of a sudden break because of this. (E.g. there may be use
cases where this kind of reflectiveness is applied to situations where Java code runs under
different versions of Java with a low baseline, where the code running on newer versions of Java
uses reflection to adapt to/access features only available in newer versions.)

---

To solve this centrally in the JRE (and not force existing, proven and legitimate code to break and
then force it to be reprogrammed, retested and redeployed, if that option existed at all) would
allow such Java code to remain compatible with the upcoming Java 9 as well.

Maybe it is possible somehow for the new code supervising invoking methods (constructors, fields)
via reflection to take this into account when seeing that a public method (constructor, field) is at
hand and itself determining that an accessible public superclass/interface class that declares it is
available and therefore allow the invocation as was the case in the past?

---rony

P.S.: A wild/crazy idea would be to force objects returned from other modules somehow to be "boxed"
to the defined return type, such that a getClass() in this situation would return solely the return
type's class. So in our example such a speculative boxing would have to be applied by public method
getDefaultToolkit() when returning an object from a module that is not known to be open for others
at runtime. Some sort of a new ProxyBox... :)




On 06.01.2017 09:24, Alan Bateman wrote:
> On 05/01/2017 20:07, Phil Race wrote:
>
>> Sort of .. it depends whether you could use getDeclaredMethod instead.
>>
>> One question I have is, how would you update the code if you
>> were given the instance "foo", and need to programmatically
>> work out what is the correct super-type of Foo that exports
>> the interface method "bar" ?
>>
>> i.e you don't have the string "java.awt.Toolkit" handy and
>> need to infer it from the instance class.
> There have been a couple of threads here (going back to 2015) on this topic. Peter included a
> method [1] in one threads to walk the superclasses and directly implemented interface of each
> class to find the accessible method. Rony's example might need someone like this if the reference
> to java.awt.Toolkit is not available.
>
> -Alan
>
> [1] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-September/009357.html
>



More information about the jigsaw-dev mailing list