[jsr294-modularity-eg] Module boundaries
Alex Buckley
Alex.Buckley at Sun.COM
Wed Feb 4 04:32:35 EST 2009
Yes, setting module membership at runtime effectively simulates
'internal', where the .NET assembly-build operation is done lazily.
Module nesting sounds interesting. Could you please send some source
code which exhibits how it would impact module-private accessibility?
We can certainly have a phone call. I am travelling internationally for
the next week and, in practice, will not be back in the office until
Tuesday 17th.
EG members, please indicate when on 17-20th February you could be
available. Good times would be 9am West Coast, 12pm East Coast, 6pm France.
Alex
Peter Kriens wrote:
> Ok, so you allow a module boundary to be set in runtime, this will make
> the module keyword in unbound modules reflect the semantics of the .NET
> 'internal' concept? I agree we should then have a discussion later about
> how the compiler gets the unbound module boundaries.(Do we have an
> action list for these things?)
>
> If I look at software projects than there will be a tendency to put a
> set of related packages into a bound module, where a number of these
> bound modules are packaged in a JAR (the unbound module). This seems to
> scream for nesting of bound modules?
>
> VM -> unbound module -> bound module +-> package -> type -+
> ^ | ^ |
> +--------------+ +--------+
>
> And, can we please, pretty please, have a kick-off phone conference now
> we're a group starting to work on this?
>
> Kind regards,
>
> Peter Kriens
>
> On 3 feb 2009, at 01:47, Alex Buckley wrote:
>
>> .NET is not Java.
>>
>> Compiled types in .NET live in non-executable modules (.netmodule
>> files). To be executed, modules must be packaged into assemblies
>> (.dll/.exe files).
>> This packaging makes "internal" a bit tricky. "internal" is specified
>> as "accessible from the same program", where a program is merely a
>> bunch of source files. A C# compiler must take it on trust that the
>> .netmodule which accesses an "internal" artifact will be packaged in
>> the same assembly as the .netmodule which declares the artifact.
>>
>> This is not unreasonable, since .netmodules MUST be packaged. But if
>> packaged "wrongly", code accessing an "internal" artifact which the
>> compiler promised was accessible will fail at runtime. You do not want
>> language features to behave like this. There is effectively a hole in
>> the C# spec caused by the greater CLI spec stratifying loadable code
>> into non-executable and executable.
>>
>> Java is different. A JVM does not require classfiles to be packaged in
>> any way before executing them. Nor does the reference implementation
>> of a Java compiler require classfiles to be packaged before compiling
>> against them. These things are not going to change. Since
>> module-private accessibility is a language and VM construct, it cannot
>> depend on the future packaging of code still being compiled or
>> compiled against.
>>
>> (What it can depend on is an API consulted by a Java compiler to
>> discover whether module M version X and module M version Y have
>> "equal" versions. The API implementation would be honor-bound to give
>> consistent answers, similar to classloaders. We'll get to that API
>> soon, I hope.)
>>
>> This boils down to saying the module-private accessibility and module
>> membership go hand-in-hand for me. In any case, the first thing a
>> programmer will ask when seeing a module-private member is: "What
>> module does this member belong to?". The answer should NOT be "it
>> depends on a compiler flag or invocation of jar".
>>
>> I will shortly send a Java language grammar and classfile format which
>> reflect these views.
>>
>> Now, I know this issue is not going to go away. I therefore propose
>> that IN ADDITION to encoding module membership in source, it should be
>> possible for the host system to determine module membership. If you
>> REALLY want the answer above to be "it depends on a compiler flag or
>> invocation of jar", you can do that. But a Java compiler/VM must defer
>> to the membership in a source/class file if it exists.
>>
>> Is that enough of a weakening of my requirements #1 and #2?
>>
>> Alex
>>
>> Peter Kriens wrote:
>>> Hmm. .NET shows that you do not have to know all the module
>>> boundaries during compilation. 'internal' indicates inside the
>>> assembly and the source assembly is clearly not known during
>>> compilation. This concept looks attractively simple and is in line
>>> with common practice.
>>> For 294, during compilation, the JAR files and project source can
>>> easily be used inside the compiler for the scope. During runtime, the
>>> module system can set this boundary.
>>> However, I also like a module concept that is defined in the
>>> language. This will be more complex (and probably should be
>>> hierarchical) but it should be not attempt to define the deployment
>>> artifact nor dependencies. That is, it should be more like namespaces.
>>> Kind regards,
>>> Peter Kriens
>>> On 28 jan 2009, at 03:56, Alex Buckley wrote:
>>>> I am happy to discuss module-private accessibility first, in that it
>>>> addresses the limitations of packages on which we all agree.
>>>>
>>>> The issue we cannot ignore is that to check module-private
>>>> accessibility at compile-time means knowing the modules to which the
>>>> requesting and requested types belong. If I invoke:
>>>>
>>>> javac Foo.java Bar.java
>>>>
>>>> where Foo.java refers to Bar, then a compiler must be able to
>>>> compute at least the module name to which Foo belongs as Foo is
>>>> compiled, if Bar is found to be module-private as it is compiled.
>>>> There are no deployment artifacts around yet. It shouldn't be a
>>>> surprise that Foo.class and Bar.class are subsequently emitted to
>>>> encode their module membership.
>>>>
>>>> So with module accessibility comes module membership. Module
>>>> dependencies are a quite different topic which we'll get to soon
>>>> enough, and they are the place where minimizing new concepts is
>>>> essential.
>>>>
>>>> Alex
>>>>
>>>> Peter Kriens wrote:
>>>>> I think it would make sense to work from first principles
>>>>> 1. What problem are we trying to solve?
>>>>> 2. How do we scope this problem to an acceptable area for all?
>>>>> 3. What requirements should the solution fulfill
>>>>> I would like to have a short discussion about the problem so we are
>>>>> sure we are all on the same page. I can start off with the problem
>>>>> I think we are trying to solve.
>>>>> Modularity
>>>>> Modularity is the art of encapsulation and hiding. A module limits
>>>>> the amount of information outside its boundaries. This reduces the
>>>>> overall complexity of a system because it becomes possible to
>>>>> reason (and change) locally about a module instead of understanding
>>>>> the whole system, and it provides a local namespace that is easier
>>>>> to work with for humans than a global namespace.
>>>>> Java provides modularity in many places. A type encapsulates its
>>>>> fields and methods and selectively exposes them to other types with
>>>>> the access modifies: private, protected and public. A package
>>>>> encapsulates a number of types and resources. And last, but not
>>>>> least, the class loader provides a class space that can be distinct
>>>>> from other class spaces.
>>>>> The modularity that is enabled with class loaders has been
>>>>> exploited by many. However, the Java Language has little to say
>>>>> about class loaders; it is outside the scope of the language.
>>>>> So what problem do we need to solve, seeing that Java provides
>>>>> already so many forms of modularity? There is a sense in the
>>>>> community that packages are too small for modules. Though the
>>>>> package names hint at a hierarchy (and this is how they are found
>>>>> in a file system), this hierarchy does not provide a preferential
>>>>> treatment for children. Many programs consist of hundreds of
>>>>> packages. However, except for the limited package concept, the
>>>>> programmer cannot indicate that the visibility of an artifact
>>>>> should be limited to the program, or part of the program.
>>>>> A large number of delivery formats have been created over the
>>>>> years, most of the based on the JAR format (which is also not a
>>>>> part of the language): WAR, EAR, OSGi bundles, midlets, xlets, and
>>>>> likely many more proprietary formats. Usually, the modularity of
>>>>> these modules is based on a rather simplistic hierarchical class
>>>>> loader model. That is, all classes in ancestors are visible, but
>>>>> not any siblings or their children. The language is moot on the
>>>>> point of this type of encapsulation.
>>>>> Delivery modules contain types that depend on types in other
>>>>> delivery modules. There is no uniformly agreed Java standard to
>>>>> model these dependencies. During build time, the compiler is
>>>>> provided with a linear list of JARs and the compiler picks the
>>>>> first type that matches a name. Only the name is encoded in the
>>>>> class file, not the originating delivery module. During runtime,
>>>>> the same process is used to find classes, albeit in a hierarchical
>>>>> class loader model. This has all so far been outside the Java
>>>>> Language.
>>>>> It is crucial that we distinguish the language/logic modularity and
>>>>> the modularity based on the deployment artifact. Interestingly, in
>>>>> my understanding, .NET makes such a distinction between the
>>>>> modularity of a delivery unit (called an assembly) and the finer
>>>>> grained modularity inside a delivery unit, represented by
>>>>> namespaces. The "internal" keyword indicates that the artifact is
>>>>> visible only inside an assembly and the "namespace" keyword
>>>>> provides a hierarchical namespace.
>>>>> Therefore, one can identify two problems in the Java platform
>>>>> concerning modularity
>>>>> 1. Packages are too limited for proper language/logic modularity
>>>>> 2. Lack of a runtime module concept that is related to deployment
>>>>> artifacts (physical modularity)
>>>>> Looking at the proposed time frame (EDR by mid-April), attacking
>>>>> both problems simultaneously seems rather unrealistic based on my
>>>>> limited experience. I therefore suggest to start with problem #1:
>>>>> Packages are too limited for proper language/logic modularity. What
>>>>> do you think?
>>>>> Kind regards,
>>>>> Peter Kriens
>>>>> On 27 jan 2009, at 05:31, Alex Buckley wrote:
>>>>>> Comments welcome.
>>>>>>
>>>>>> 1) Packages are typically arranged in hierarchies, but types can
>>>>>> only be
>>>>>> used across different branches of the hierarchy by being made public,
>>>>>> which exposes implementation details too widely. Information
>>>>>> hiding is
>>>>>> further reduced by interface members always being public.
>>>>>>
>>>>>> Non-solution: hierarchical package membership. Redefining existing
>>>>>> well-known semantics is always a bad idea, and this one is especially
>>>>>> complicated. There would need to be a way to stop package-private
>>>>>> artifacts from being accessible to subpackages, or else we would be
>>>>>> strengthening information hiding in one place only to weaken it
>>>>>> elsewhere. Also, there would need to be a way to configure the
>>>>>> depth of
>>>>>> exposure of package-private artifacts, since artifacts in package A
>>>>>> should sometimes be accessible to A.B and not to A.B.C, and so on.
>>>>>>
>>>>>> 2) Dependencies of one type on another are expressed in source and
>>>>>> classfiles, but there is no standard way for a Java compiler or
>>>>>> JVM to
>>>>>> interact with its environment to read and resolve dependencies. This
>>>>>> causes compile-time and runtime environments to differ, and
>>>>>> complicates
>>>>>> any effort to version types available in the (compile-time or
>>>>>> runtime)
>>>>>> environment.
>>>>>>
>>>>>> Non-solution: standardize the CLASSPATH. One list for all programs
>>>>>> and
>>>>>> libraries in the JVM makes versioning almost meaningless, and
>>>>>> packages
>>>>>> whose types occur in multiple CLASSPATH entries can behave poorly.
>>>>>> (See
>>>>>> Peter Kriens' presentation at Devoxx 2008.)
>>>>>>
>>>>>> 3) Many packages have grown large over the years. They are
>>>>>> effectively
>>>>>> impossible to refactor now, since it is binary-incompatible to rename
>>>>>> types and dangerous to "split" packages. The next-best option is
>>>>>> to let
>>>>>> subsets be taken of existing packages, and deliver subsets
>>>>>> independently, but there is no mechanism in the Java language or
>>>>>> JVM for
>>>>>> that.
>>>>>>
>>>>>> Non-solution: a mechanism for renaming packages and types outside the
>>>>>> Java language. This would require updating Java's model of binary
>>>>>> compatibility, and would make source code incomprehensible.
>>>>>>
>>>>>> Alex
>>>>>> _______________________________________________
>>>>>> jsr294-modularity-eg mailing list
>>>>>> jsr294-modularity-eg at cs.oswego.edu
>>>>>> <mailto:jsr294-modularity-eg at cs.oswego.edu>
>>>>>> http://cs.oswego.edu/mailman/listinfo/jsr294-modularity-eg
>>>>> ------------------------------------------------------------------------
>>>>>
>>>>> _______________________________________________
>>>>> jsr294-modularity-eg mailing list
>>>>> jsr294-modularity-eg at cs.oswego.edu
>>>>> http://cs.oswego.edu/mailman/listinfo/jsr294-modularity-eg
>>>> _______________________________________________
>>>> jsr294-modularity-eg mailing list
>>>> jsr294-modularity-eg at cs.oswego.edu
>>>> http://cs.oswego.edu/mailman/listinfo/jsr294-modularity-eg
>>> _______________________________________________
>>> jsr294-modularity-eg mailing list
>>> jsr294-modularity-eg at cs.oswego.edu
>>> http://cs.oswego.edu/mailman/listinfo/jsr294-modularity-eg
>> _______________________________________________
>> jsr294-modularity-eg mailing list
>> jsr294-modularity-eg at cs.oswego.edu
>> http://cs.oswego.edu/mailman/listinfo/jsr294-modularity-eg
>
> _______________________________________________
> jsr294-modularity-eg mailing list
> jsr294-modularity-eg at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/jsr294-modularity-eg
_______________________________________________
jsr294-modularity-eg mailing list
jsr294-modularity-eg at cs.oswego.edu
http://cs.oswego.edu/mailman/listinfo/jsr294-modularity-eg
More information about the jsr294-modularity-observer
mailing list