My position on module security/access control

mark.reinhold at oracle.com mark.reinhold at oracle.com
Thu Dec 17 16:27:14 UTC 2015


2015/12/15 8:51 -0800, david.lloyd at redhat.com:
> On 12/14/2015 01:45 PM, mark.reinhold at oracle.com wrote:
>> 2015/12/10 8:00 -0800, david.lloyd at redhat.com:
>>> On 12/09/2015 07:29 PM, mark.reinhold at oracle.com wrote:
> ...
> 
>> Okay, I think I'm starting to get it, but in your statement
>> 
>>>>> The concept being established here is the
>>>>> ability to have a public class which is not exported but is still
>>>>> accessible to anyone.
>> 
>> the clause "is not exported" suggests that some public types are
>> "exported" and some are not.  I read this to mean that public types would
>> still be subject to some sort of access control based upon some kind of
>> export declarations, but only for static linkage.  If that's not the
>> case, then what's the distinction between "not exported" and "exported"?
> 
> Right though I prefer the existing "visibility" term for this, as this 
> term is well over a decade old and reasonably well-understood at this point.

Just to confirm: In your preferred approach an exported public type would
be made visible to class loaders other than its own for the purpose of
static linkage, but a non-exported public type would not, and whether a
public type is exported would have no bearing upon the access-control
decisions for that type made by both the VM and the reflection APIs.

Is that right?

>>>> If a Java 9 class is not inside a module, i.e., it's on the class path,
>>>> then what is the default access mode?  If it's package-private then it
>>>> would work differently than from within a module.  If it's private to the
>>>> unnamed module in which all classes found on the class path are defined
>>>> then it would work differently from any pre-9 classes on the class path.
>>>> Either outcome is likely to confuse people.
>>> 
>>> Class path private; see my other mail.
>> 
>> Okay.  Suppose that I upgrade a pre-9 component into a module using this
>> approach, and ship it as a modular JAR file so that it can be used both
>> as a module and on the class path.  If it's used on the class path then
>> any types that formerly were package-private are now accessible to all
>> other code on the class path, regardless of whether that other code was
>> compiled with 9 or with an earlier release, right?
> 
> Yes, potentially, if the class path is held as a single module (which it 
> could be, but does not have to be).  There are pros and cons to each 
> approach though.

If all classes on the class path are not loaded into a single module then
what other approach do you have in mind?

>>>> ...
>>>> 
>>>> At a higher level, I agree that the package-private access mode has
>>>> proved to be of limited utility.  It has, however, been a fundamental
>>>> part of the language and the VM from the very beginning.  To widen it in
>>>> such an incompatible fashion now, after twenty years, would make it more
>>>> difficult to migrate existing code to modules and would risk enabling
>>>> further security vulnerabilities.
>>> 
>>> I think this is objectively false.  Existing code would continue to have
>>> the same encapsulation; only new code would have the expanded capability
>>> and only in reference to other new code.
>> 
>> What about references from outside a module?
> 
> If class loaders are used as the representation of a module (for the 
> purposes of this discussion at least), then no code is outside a module, 
> which is highly appealing because it simplifies matters immensely.

Of course -- I was asking about references from other modules.

>> Would the default access mode on a Java 9 type mean "module private" if
>> the code attempting to access that type is itself compiled -target 9, and
>> "package private" otherwise?
> 
> I think references to Java 9 class members would have to mean "module 
> private" no matter who is accessing it, as this allows better piece-wise 
> migration to using the new access level (and from my examination and 
> understanding of the OpenJDK bytecode verifier implementation, I suspect 
> this would be simpler to implement as one only has to know what the 
> target class' version is, as opposed to applying a more complex rule on 
> both the source and target versions).  In other words, a class of any 
> version accessing a Java 8 class file uses package-private, but a class 
> of any version accessing a Java 9 class file uses module-private.

What about existing source code that's recompiled -target 9?

Suppose, e.g., that I maintain a library that dynamically generates
classes whose bytecodes depend upon user input (say, an XSLT compiler),
and that I load those classes into the same class loader as my library
(arguably a bad practice, but I've seen this before).  The synthesized
classes are in their own special package, rather than in one of my
library's packages, so today they cannot access any package-private
members of the library itself.  If I recompile my library -target 9
then that will no longer be true.

Do we really want the simple act of recompiling old code to open the
door to new security vulnerabilities?

- Mark


More information about the jpms-spec-observers mailing list