[jsr294-modularity-eg] Problems for JSR 294 to address

Hal Hildebrand hal.hildebrand at gmail.com
Mon Feb 2 11:13:35 EST 2009


On Feb 2, 2009, at 7:58 AM, 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.

This is something I was wondering.  How can it be that .NET can do  
this, but the gods of Java are unable to figure out how to accomplish  
this.

> 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



More information about the jsr294-modularity-observer mailing list