[jsr294-modularity-eg] Pain

Peter Kriens peter.kriens at aqute.biz
Wed Jul 15 10:47:23 EDT 2009


On 15 jul 2009, at 01:13, Bryan Atsatt wrote:
> I think we've been around this circle before: module names in  
> source, nested modules/containers, module system specific clauses in  
> the declaration, etc. Still not buying.
This is only the stuff that was given as an answer to Alex's challenge  
to get details. They're not that relevant imho, just to show that  
there is a way out the core problem.

The core issue I am raising is that we make the Java language depend  
on the module system, which is fundamentally wrong. Instead of  
cleaning up the fuzziness introduced by class loaders, we do the  
reverse and bring the fuzziness into the, so far, pure JLS.

Kind regards,

	Peter Kriens







>
> I am all for standardizing the "require" directive as much as  
> possible, and the semantics that 'require module' == all of its  
> public packages (with no split packages). OSGi can support 'require  
> bundle' with the split package semantic if it wants to. It should  
> also support 'require package', rather than using a different  
> directive like 'import'.
>
> I am even in favor of standardizing a version/range syntax, but only  
> if we also provide Version/VersionRange classes that are syntax  
> agnostic.
>
> My issue at the moment with the proposed drafts is that the api doc  
> is incomplete and so it is hard to see how this all hangs together.  
> I'll send a more complete (and refactored) api in a separate message.
>
> // Bryan
>
> Alex Buckley wrote:
>> Bryan, BJ, Doug, Sam, Bob, Daniel,
>>
>> What are your opinions on Peter's mail?
>>
>> Alex
>>
>> Peter Kriens wrote:
>>> First, I think it is a fallacy to require to have the solution  
>>> before you yell fire. However, many of the ideas I stand for are  
>>> reported in the document I wrote when we started. Obviously there  
>>> is some evolution, so let me elaborate a bit more. The following  
>>> is obviously a sketch. More than willing to work this out in  
>>> detail if it has a chance.
>>>
>>> Modules
>>> In the JLS we define a clean concept of module like .NET  
>>> namespaces/Ruby/Modula etc. It is hierarchical and it is part of  
>>> the Java source + class file.
>>> module com.acme.foo;
>>> package main;
>>> import com.acme.bar.*;
>>> import module org.osgi.service.log;
>>> module class A{}
>>>
>>> The type names are module name + package name + type name. I.e. in  
>>> the previous example com.acme.foo.main.A. This is 100% compatible  
>>> with our current model and fits the current JLS very nicely. This  
>>> will simplify learning and porting.
>>>
>>> Jigsaw wants permits and OSGi has some resistance here. I there  
>>> fore propose an implementation import in your compilation unit:
>>>
>>> import implementation module com.acme.impl;
>>> import implementation com.acme.impl;
>>>
>>> This will import all public and unspecified access packages but  
>>> not private packages. By specifying the implementation keyword,  
>>> you indicate that you're willing to suffer the consequences of  
>>> using non-specification code. If security is on, we can prevent  
>>> using this with security if the exporter really does not want it.  
>>> Without security, you can do anything already so who cares. This  
>>> model seems better than the reverse dependency model that permits/ 
>>> friends creates.
>>>
>>> You can nest modules: com.acme.foo/test
>>>
>>> module com.acme.foo;
>>> module test;
>>> package performance;
>>>
>>> class PerformanceTest {}
>>> A module info would NOT contain any dependencies and other  
>>> packaging info, Only the top level module can have this. It can of  
>>> course contain annotations.
>>>
>>> The package-info gets the capability to make a package public,  
>>> implementation, or private:
>>>
>>> com/acme/foo/main/package-info.java:
>>> module com.acme.foo;
>>> private package main;
>>> com/acme/foo/service/package-info.java:
>>> module com.acme.foo;
>>> import module aQute.bnd.annotations;
>>> @Version(1.2)
>>> public package service;
>>> A public package is intended to be exported by the container and  
>>> made available to others. A private package is local to the  
>>> container, if not specified, it is allowed to be imported by  
>>> classes import it as an implementation module (this prevents the  
>>> need for friends). That is, types in a private package are not  
>>> accessible outside the container. The default is private.
>>>
>>> If you import a module, you get visibility to all public packages  
>>> but no private packages. That is, it looks like you do an import  
>>> for each package marked public in the module with a * at the end.
>>>
>>> module accessibility is roughly defined as having access to your  
>>> module + any higher modules. If you're not part of an explicitly  
>>> defined module, you're part of the container. That is, the JLS  
>>> must introduce the concept of a container and the container needs  
>>> a container-info compilation unit. This unit is conceptually found  
>>> at the root of the compilation tree. In this file, you describe  
>>> your dependencies on other containers. The container file has all  
>>> the messy stuff that we spent most of our time talking about.  
>>> However, it has the following things standardized:
>>>
>>> name (which is like a fqn)
>>> version (a JSR 294 defined syntax, we MUST standardize this, it is  
>>> ridiculous to leave this open)
>>> required modules
>>> optional public key
>>> module system specific info
>>>
>>> For example:
>>>
>>> container-info
>>> container com.acme.foo {
>>> version 2.1;
>>> key 1234567812121212121211212121212;
>>>
>>> require com.acme.bar, version=[2.1.2,3);
>>> require com.acme.util, version=[2.3.2,3);
>>> require com.acme.bar, version=[1.3,2);
>>> command foo;
>>> org.osgi {
>>> version 4.3;
>>> bundle-license "ASL 2.0";
>>> }
>>> com.sun.jigsaw {
>>> version 0.91;
>>> permit com.acme.yui;
>>> }
>>> }
>>>
>>> However, it is NOT compiled by the compiler, the compiler ONLY  
>>> interprets this file, as do all the tools that need access to this  
>>> information like ant, etc. However, the compiler records the exact  
>>> version of the container against which it compiles in the class  
>>> files of each compilation unit. That is, from the class file we  
>>> know exactly the container we compiled against.
>>>
>>> I think this concludes the JLS part ... Now, the JDK part
>>>
>>> We need to reify the container into a JAR or some other artifact.  
>>> This will be done by a tool like jar. This tool will create a  
>>> container that has a container-info.class file. It contains a  
>>> summary of:
>>>
>>> all actually used containers with the name, version, key, and  
>>> indicated version range
>>> all public packages
>>> module system specific information (with the info if the ms is  
>>> required or optional)
>>>
>>> The tool has a plugin model to create module system specific  
>>> information. For OSGi, in this phase we can translate the  
>>> information to import packages to reduce the fan-out and  
>>> optionally do some other tricks that reduce deployment problems.  
>>> Obviously, we can also calculate the uses constraints. Jigsaw just  
>>> does what it needs to do. All information is collected in the  
>>> container-info.class file.
>>>
>>> As some will wonder, why do I accept requires? Well, during  
>>> development time I think the coarse granularity of containers is  
>>> nice, I just think that at the runtime their fan-out is too large  
>>> for comfort. I the sketched process, the container reifying tool  
>>> can handle this conversion with a plugin.
>>>
>>> The next phase is runtime! I think we need a repository associated  
>>> with a JVM. The still 100% standardized containers are inserted  
>>> into the repository. A module system must have the facility to  
>>> optimize the artifact for its deployment, for example, it must be  
>>> able to maintain an OBR index. The insert in the repository must  
>>> also verify the command option in the container-info. If this is  
>>> set, it should create a command on the file system so the program  
>>> can be run from the command line and/or desktop.
>>>
>>> The java command gets an option to run a container. E.g.
>>>
>>> java -run com.acme.foo
>>>
>>> The java looks in the repository and finds the container  
>>> com.acme.foo. It looks to see what the container-info says about  
>>> module systems and picks the first listed module system that is  
>>> available in the vm (which should also be in the repository). It  
>>> then passes control to the module system that resolves the given  
>>> com.acme.foo and runs it. Alternatively, because foo is also  
>>> registered as a command in the container, it can also run it:
>>>
>>> $ foo
>>> Or
>>> c:\>foo
>>>
>>> The module system is fully in control of what happens at runtime.  
>>> It has access to the repository and can install containers when it  
>>> needs to. A module system can also reuse the information from  
>>> other module systems. For example, an OSGi framework could  
>>> interpret the data from jigsaw and emulate their model. We could  
>>> also look to see if there is Guice information in the container- 
>>> info and run that as well.
>>>
>>> Again, this is a sketch, let me know if I should work out all the  
>>> unspecified details. Kind regards,
>>>
>>> Peter Kriens
>>>
>>>
>>>
>>> On 9 jul 2009, at 19:26, Alex Buckley wrote:
>>>
>>>> What would you like to see happen? Details please.
>>>>
>>>> Alex
>>>>
>>>> Peter Kriens wrote:
>>>>> As you probably have noticed, I am not very happy where we are.  
>>>>> Instead of providing a singular model based on best practices,  
>>>>> we worsen the situation by introducing the world's first meta  
>>>>> module system that is completely outside whatever we already  
>>>>> have in Java. And while we're at it, we're not fixing any of the  
>>>>> known deficiencies. Alas, we are not standardizing Java modules,  
>>>>> we are agreeing to go our own way.
>>>>> We are not reusing any Java concepts, the complete definition of  
>>>>> module is left to the module system. And sadly, Java has  
>>>>> modules, they were called packages. As the JLS says: "Chapter 7  
>>>>> describes the structure of a  program, which is organized into  
>>>>> packages similar to the modules of Modula." In 294, instead of  
>>>>> building on the existing Java Language constructs and fixing its  
>>>>> shortcomings, we went off on something that is a hybrid  
>>>>> of .NET's namespace and assemblies. I invariably notice that  
>>>>> when 294 is discussed people are in the ".NET namespace/Ruby  
>>>>> modules" world or in the ".NET assembly/Ruby gems" world, it is  
>>>>> rare that I feel that the subtle distinctions and overlap in  
>>>>> concepts is clearly understood. Hey, I am not even sure I get  
>>>>> it. At the same time, each camp seems to have a clear view what  
>>>>> it will get out of 294. Which I guess over time they will when a  
>>>>> cotton industry of module systems has arisen, but in a Java  
>>>>> world where the word Java is no longer sufficient to define the  
>>>>> language.
>>>>> Module is a well defined word but it is fractal. A code block is  
>>>>> a module, method is a module, a class is a module, a package is  
>>>>> a module, a library is a module, and a program is a module. They  
>>>>> all have an inside and an outside, where different rules apply.  
>>>>> My problem with the current design is that it does not define  
>>>>> anything that fits nicely in this hierarchy or even resembles  
>>>>> existing Java concepts; it will leave details up to the module  
>>>>> system. This will make the source code no longer portable, the  
>>>>> antithesis of Java :-( Yes, I can see lots of cool features we  
>>>>> can provide with the Eclipse compiler and the OSGi runtime but  
>>>>> it saddens me that this will fragment the Java world, forcing  
>>>>> the user to find out the features that are portable between  
>>>>> module systems or committing to their favorite module system.
>>>>> In Java 1..6 the language offered a pretty pure model that was  
>>>>> mapped to reality in the VM. With class loader tricks we could  
>>>>> tweak the perspective each JAR had of this pure world, solving  
>>>>> many real world problems. In JSR 294, we will for the first time  
>>>>> introduce this messy and complex runtime world in the language.  
>>>>> Untold millions have been spent to make Java run on hundreds of  
>>>>> platforms, and with one simple JSR we bring back the need for  
>>>>> #ifdef ...
>>>>> Kind regards,
>>>>> Peter Kriens
>>>>> ------------------------------------------------------------------------
>>>>> _______________________________________________
>>>>> 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 <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-eg mailing list