[jsr294-modularity-eg] Module boundaries
Peter Kriens
peter.kriens at aqute.biz
Wed Feb 4 03:02:45 EST 2009
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
More information about the jsr294-modularity-observer
mailing list