Exporting - the wrong default?

Xavier Miró xmirog at gmail.com
Fri Jul 29 09:06:46 UTC 2016


   I've read very good ideas and I think that we are very close to a 
reasonable solution for the majority of use cases. I have imagined how I 
would organize my source code in a modular world and this is how I see a 
possible solution using your good ideas:

  1) I agree completely with Rémi on the default case 2 (don't see it at 
compile time, see it at runtime).
  2) I would add the possibility of using wildcards to the 'exports' (I 
think David has also commented about it)
  3) I would also use the syntax that Stephen talks about, but to 
restrict completely (both in compile time and in runtime) the "secret" 
packages, like the JDK internal classes.

   So I would organize my packages this way:

   - Packages to be exported (the "API", available at runtime and 
compile time):
       - com.foo.myproject.package1
       - com.foo.myproject.package2

   - Internal packages (only available at runtime):
      - internal.com.foo.myproject.package1
      - internal.com.foo.myproject.package2

   - Hidden packages (not available neither at compile time nor at runtime):
     - hidden.com.foo.myproject.package2

    In the module-info file I would write:

module com.foo.myproject {
   .. (requires, uses, etc.)
   exports com.foo.myproject.*;
   restricts hidden.*;
   ..
}

   With this convention and the wildcard, the problem of forgetting to 
export a package or to restrict a package is reduced (of course it can 
happen that I forget to put the export line, but as nothing would be 
exported the build tool could emit a warning). At least, once written 
the line and following the convention of the packages it would be more 
difficult to leave a package without export unintentionally. The 
convention is not enforced by the system, nothing prevents to use 
non-wildcard 'exports' or 'restricts' or to put the packages in other 
places.

   This mixed proposal is based on the idea that exporting at runtime 
makes no harm unless otherwise specified (with 'restricts'), so I think 
that in this context the 'exports static' wouldn't make sense. As the 
default is a 'exports dynamic' implicitly, it wouldn't be necessary to 
have it as an explicit statement.

   The qualified exports and qualified restricts would work as in the 
other proposals.

So as a summary of the export visibility:

exports => compile time=yes, runtime=yes
(default) => compile time=no, runtime=yes
restricts=> compile time=no, runtime=no

   I'm sure this solution has "holes", I'm not a Jigsaw expert, but I 
hope that reading it can help the JSR experts to find a good proposal.

         Xavi


On 27.07.2016 17:26, Remi Forax wrote:
> ----- Mail original -----
>> De: "dalibor topic" <dalibor.topic at oracle.com>
>> À: jigsaw-dev at openjdk.java.net
>> Envoyé: Mercredi 27 Juillet 2016 14:39:05
>> Objet: Re: Exporting - the wrong default?
>> On 26.07.2016 18:42, Stephen Colebourne wrote:
>>> In many projects
>>> packages change names frequently during development, everything is
>>> open and locking stuff down is the last thing on peoples minds. While
>>> this of course leads to slightly less secure software, it does achieve
>>> *business value*.
>> I would recommend Cristina Cifuentes presentation "Are We Ready for
>> Secure Languages?" from the recent Curry On conference, of which a
>> recording is available at https://www.youtube.com/watch?v=-fC975HLhyc
>> for some less anecdotal thoughts on the business value of slightly more
>> secure software.
>>
>> It even touches briefly on the utility of modules in JDK 9.
> Interesting talk !
>
> to get back to our issue,
> there are 4 possibilities when exporting a package, for a public type,
> (1) don't see it at compile time, don't see it at runtime (can't reflect on it)
> (2) don't see it at compile time, see it at runtime (this is the OSGI/JBoss model for not exported)
> (3) see it at compile time, may not exist at runtime (so be prepared to get an exception then)
> (4) see it at compile time and see it at runtime
>
> The default can not be (3) because it's a corner case, it can not be (4) because in that case we lost the 'strong encapsulation' that a module should provide by default, so the default can be either (1), either (2) or to force the user to choose between (1) and (2) when declaring a module.
>
> The problem with (1) is that:
>   - it makes most of the code that use reflection not working (and as Stephen said, at lot of codes use reflection (or bytecode generation)),
>   - it will slow down the adoption of jigsaw (not jdk9 which will be run with a -classpth) but the modularization of the already existing jars, so we will end up with a module system which will be not used or worst, some jars will be modularized, some will not and we will be in the same sad state of Python now with 2 mostly compatible worlds *.
>
> The problem of letting users to choose is that the hope to educate them by forcing them to make their own choices will be destroyed because in practice IDEs will chose for them (e.printStackTrace() anyone ?)
>
> So the only valid choice seem to be (2), which
> - still enable JDK and application server implementation modules to not export some types at runtime, so the security will improve and by example, it will avoid most of the access control bugs Christina talk about.
> - the default behavior will make the move to convert their jars to modularized jars easier because people will not conflate the problem of the modularization itself with the problem of the access control at runtime.
> - everybody will be happy and we will not see angry ponies on slides about Java 9.
>
>> cheers,
>> dalibor topic
> cheers,
> Rémi
>
> * Or, at some point, someone will also find that by using jlink and creating its own module Layer, he can have a 'Java' launcher with its own defaults.
>



More information about the jigsaw-dev mailing list