Non-exported vs restricted packages

David M. Lloyd david.lloyd at redhat.com
Fri Dec 4 12:53:52 UTC 2015


On 12/04/2015 03:10 AM, Remi Forax wrote:
> Hi All,
> I think there is an issue with the current design of jigsaw that we should tackle.
>
> The problem have been raised several times of the jigsaw-dev mailing list by different people and I think it's a valid point, currently the way encapsulation is specified doesn't match with the way people use/want to use modules in an application server. Don't get me wrong, I don't not want to have stronger encapsulation that we currently have, i just think we should recognize that the way people currently use modules is a valid use case.
>
> So the problem is that most application servers use reflection to create instances of implementation of an interface and people want the implementation on that interface to be in a non-exported package. With Jigsaw only option if you want this configuration is to use a ServiceLoader to load the implementation.

To me the problem isn't the encapsulation itself - it's the manifold 
issue that (A) you can't realistically opt out of it, especially only 
for certain types, (B) it introduces a second mechanism beyond 
traditional accessibility to control accessibility for no good reason, 
(C) even if you could somehow opt out of it in a Jigsaw-friendly way 
(annotations or package lists or something), the default is still to 
break everything that makes the perfectly reasonable assumption that 
public means public, (D) these things add up to likely instant 
incompatibility for hundreds, possibly thousands, of existing public 
projects and artifacts (let alone private things), etc.

> But using a ServiceLoader requires coordination between the code that declares and uses the interface and code that implements that interface. Which mean that people will be able to use modules in an application server when the application server itself will use ServiceLoader, so not before JavaEE 9.
>
> I think we should provide a way for people to use modules in a JavaEE 7/8 world.
>
> The way to do that is to recognize that we should have a way to specify that we want packages that have implementations that are not accessible directly but that are accessible using reflection (with the right handsake). It doesn't mean we don't want stronger encapsulation for package like com.sum.foo, it means we also want to have a way to specify that a package can be non-exported but its implementations can be available by reflection if and only if setAccessbile is used.

But are packages really the right unit of granularity for this?  I think 
it is reasonable to want to have, in one package, classes that are 
public and classes that are private to a module.  In the wild, I believe 
that existing usage of package-private access level shows clearly that 
this would be a common pattern, if it were even possible to do.

> This will ease the transition by allowing people to modulify there current code without waiting application servers to implement the JavaEE 9 spec because application server vendors can tweak the implementation of their dependency injection mechanism to use setAccessible when necessary*.

I definitely agree that we need a way for current code to be seamlessly 
modularized.

> So I propose that the spec should specify three kind of packages "availability",
> exported packages that make classes available by module that require the module containing the packages, non-exported packages that make classes non available but that can be used by reflection using setAccessible as an escape hatch and restricted packages that make the classes non-available even by using setAccessible.

This is getting a bit complex, no?

> Note that the question of which one should be the default is another question that can be decided after.
>
> Rémi
>
> * we also need setAccessible to add a read edge automatically if the package not restricted.
>

-- 
- DML


More information about the jpms-spec-observers mailing list