visibility, readability, accessibility and reflection

Peter Levart peter.levart at gmail.com
Thu Dec 3 17:12:35 UTC 2015


Hi,

If there are two modules:

module a {
     requires b;
}

with class:

package p;
public class C {
     public static void main(String[] args) {
         new q.D();
     }
}

and:

module b {
     exports q;
}

with class:

package q;
public class D {
}


...then for a constructor invocation expression in p.C:

     new q.D();

to compile and run, three things must hold (two for compile, three for run):

- module a must read module b
- module b must export package q to at least module a
- class q.D must be visible from class p.C meaning that they must either 
be loaded by the same classloader or the classloader of p.C must 
delegate to the classloader of q.D directly or indirectly

Now lets exchange this constructor invocation expression with equivalent 
reflection code in p.C::main:

     Class<?> dClass = Class.forName("q.D");
     dClass.newInstance();

To run these two statements the same three things must hold. I would 
expect that individual statements need the following:

     Class.forName("q.D");

- module a must read module b
- class q.D must be visible from class p.C meaning that they must either 
be loaded by the same classloader or the classloader of p.C must 
delegate to the classloader of q.D directly or indirectly

     dClass.newInstance();

- module b must export package q to at least module a


But in fact, the newInstance invocation also needs:

- module a must read module b


So it seems that readability is checked both times. I would like to know 
what is the reasoning behind that. Since visibility (class loading) must 
be aligned with readability (read edges / requires), I was not expecting 
module system to demand readability where visibility is not required 
(like for example in invocation through reflection). When the 
constructor is invoked via bytecodes:

     new q.D();

two things are performed:

     - class D is resolved (needs visibility and readability)
     - access to D/D.<init> is performed (needs accessibility)

With reflection, I would expect Class.forName() to be the resolving part 
and .newInstance() to just be accessing the class/member.


Regards, Peter



More information about the jigsaw-dev mailing list