Feedback on proposal for #ReflectiveAccessToNonExportedTypes
Alan Bateman
Alan.Bateman at oracle.com
Thu Jul 21 20:45:09 UTC 2016
Just a few comments on the examples posed in the last mail.
On 21/07/2016 18:01, Jason Greene wrote:
> :
> That would help, but there is also class visibility issues that would need to be addressed as well.
>
> Example 1 (Ambiguous class names):
>
> Both A and B export “bar”, and both define “bar.MyClass” which have differing definitions. Victim could load the supposed to be hidden A’s MyClass instead of the intended B’s MyClass.
>
> There is also a variant of this where the conflict is between Victim and A if A also exports another hidden package that is present in Victim itself.
If the scenario were:
A exports bar
B exports bar
Victim requires A; requires B;
then it would be a split package issue and would be rejected at
resolution time (or more specifically, one of the post resolution
checks). The simple rule is that two or more modules can't export the
same package to a module that reads both. This includes the case where a
module M containing package p reads another module that exports p to M.
If the scenario is:
A exports dynamic bar
B exports bar
Victim requires A; requires B;
then, with the updated semantics, there is no split package issue at
resolution time. Victim reads module A and module B but the `exports
dynamic` edges are ignored by the post-resolution checks. If it "as if"
Victim invokes addReads(A), nothing more.
Moving on to the class loader delegation graph then it needs to support
the readability graph and exports. With the updated semantics then any
reference to bar.MyClass in Victim will delegate to the loader of module
B. Victim's loader doesn't know anything about package bar in module A.
There are of course dozens of ways in which a Class object for some type
bar.* type in module A could leak to Victim, maybe it uses Class.forName
specifying module A's loader. Assuming code in Victim gets a reference
to a public type in module A's bar package then it will be accessible to
code in Victim (as intended in the scenario I think).
> Example 2 (Unintentional discovery):
>
> Victim uses ClassLoader.getResources (plural), looking for a standard configuration file or class name, and receives entries for both A and B. A’s was not intended to be discovered by victim, and leads to a failure state. As an example perhaps the configuration file in B specifies a class name in B’s dependency, which is not visible to Victim. Or, perhaps A’s config leads to duplicate runtime actions being configured (since the file was really only indented for A, which also processes it)
In this scenario then I can't tell if the "should-not-be-discovered" A
type is an exported package or not. If it's a public type in a package
exported to Victim then it will be accessible to code in Victim. If it's
not in an exported package then it won't be accessible.
Whether it's visible is another question, that depends on how the class
loaders and delegation are arranged. In the simple case then A, B, and
Victim are all defined to the same class loader. That would allow Victim
to load any type in A but only the public types in A's exported packages
would be accessible.
For the scenario where the file lists some class in a random module B
reads, say module C, then it may or may not be visible to Victim. It
might be able to load it, it might not. Assuming it is visible then it
may or may not be accessible. There isn't enough in the example scenario
to know if this type is in a packaged exported by C or not.
-Alan.
More information about the jigsaw-dev
mailing list