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