You'll no longer need to distribute the entire JRE API if your app needs an embedded JRE. You'll be able to distribute only the modules you need.
For example, I'll no longer be including the useless (for most Java apps) CORBA capability with my product. A server-side product will be able to exclude the desktop GUI API (AWT and Swing).
> A server-side product will be able to exclude the desktop GUI API (AWT and Swing).
That is very unlikely. If you look at the java.desktop module (where things like AWT and Swing are) there are also tons of other things there like Java Beans. A lot of Software requires Java Beans at least indirectly (eg. Spring requires Java Beans). In addition there's the following dependency path.
java.xml.ws -> java.xml.bind -> java.activation -> java.desktop
A server side product is very likely going to require at leat one of these.
The fact of the matter is that the JDK code is simply not modular enough.
The java.desktop module is going to be a prime candidate for further breakdown, probably after Java 9 I guess. It is huge and ships all 3 widget toolkits when most apps need only one.
What's the third one? I'm only aware of AWT and Swing. I though that JavaFX was already in its own modules. Is it really realistic to only use one toolkit when Swing is built on AWT and has AWT base classes?
What bothers me more is that things like Java Beans are in java.desktop.
Currently if you want to deploy software running in the JDK, you're forced to pick up the whole JDK, which is terrible if you want to deploy as small a codebase as possible, especially because literally nobody is using Swing and AWT and Nashorn in server-side environments.
Meanwhile, currently if you want to use a module system that only deploys code you're actually transitively dependent on in Java, you have to roll your own with its own concept of dependency and versioning.
Meanwhile, currently if you want to depend on a library that's already deployed on a host, you get to discover it via the classpath mechanism, which has an element of.. randomness.. to it, and in some cases if you have two versions of the same class in your classpath you can get some very strange and hard-to-debug behavior. (I've had colleagues who wrote custom classloaders purely to work around this in the constraints of our dev environment) This combines especially badly with the ubiquitous use of 'discovery' mechanisms in enterprise Java such as static logger binding or classpath-scanning for annotations to find configurations and bean definitions.
Meanwhile, currently, the 'public' designation in a module means public to everyone in every module, and if you want to avoid that and go package-private or less, you have to be private even within other packages of your own module, since package-private is not inherited by subpackages (com.me.x and com.me.x.y do not actually 'inherit' in any sense). That is, there's no distinction between 'public' and 'exported' types.
Jigsaw attempts to address all of these. I haven't followed it closely enough to comment on whether I think it's the ideal solution, but, it's definitely the right direction if Java is to continue being used everywhere - which it is, because it's deeply entrenched and (while not as modern as some would like) it's getting the job done.
My understanding of the practical benefits is this (someone please correct me if I'm wrong)
Java currently doesn't have true packages. There's namespacing (com.companyname.abc.xyz), but it's all on a single classpath (java -cp). Dependency management like Maven gives somewhat of an illusion of packages. The end result of a Maven build is still a bunch of jars running with "java -cp".
For example, in Maven, imagine there's a json-lib 1.0 and 1.2. Library A needs json-lib 1.0 and Library B needs json-lib 1.2. Project X is using both Library A and Library B and when Maven tries to build, there will be a version conflict between json-lib 1.0 and json-lib 1.2. There are no good options at this point because the single classpath forces the selection of one version for json-lib. The developer has to either pick json-lib 1.2 and hope Library A can run with it. Or pick json-lib 1.0 and hope Library B can run with it. This is assuming Library A and Library B are external libraries that the developer has no control over and hasn't been updated in a long time.
With packages (Jigsaw), it's possible to let both versions exist in a project. It will be possible for Library A to be a package and use json-lib 1.0. And Library B will be another package and can use json-lib 1.2. During runtime, each package will have an isolated classpath and so the dependencies won't conflict. I'm assuming the Maven developers will update Maven to do this once Java 1.9 is released.
This will remove a big headache that currently exists for Java developers. The chances of a version conflict approaches 100% as the number of dependencies grows in a project.
Many people were frustrated with OSGi because it explicitly made modularity up front and centre, and the majority of developers didn't want to worry about it. The modularity of Jigsaw - including different classloaders for modules - is pretty much exactly the same as with OSGi. The differences are largely syntax and lack of versioning at this point.
Good explanation. There are currently ways to manage the issues, OSGi, classloader hacks, or using something like Maven's shade plugin. They all have their own issues and pain points though.
The other thing that Jigsaw is bringing is modularizing the standard library as well. So if you don't want CORBA in your runtime image than you can leave it out.
One thing I remember is the idea that Jigsaw is specifically for modularizing the JVM and JDK itself while OSGI would be for modularizing applications built on the JVM. Here is an article about this but it I would admit it is OSGI biased: http://njbartlett.name/2015/12/03/jigsaw-is-a-shibboleth.htm...
It isn't really but aimed at a different use case.
Everyone rallied against OSGi because the strict modularity showed developers that in general their application wasn't as modular as they thought it was; and the fact that class loaders enforced that permissioning model showed where random Class.forName and module busting code lived.
Guess what? Those developers will have exactly the same problems with Jigsaw modules.
What Jigsaw will do is educate Java developers that the pain points are in strict modularity rather than any one module system.
> Guess what? Those developers will have exactly the same problems with Jigsaw modules.
And many more. Jigsaw also locks down reflection. In addition Jigsaw lacks many work arounds that OSGi has to get software working (fragments, buddy classloading, dynamic imports, optional dependencies, capabilities, …).
Honestly I have a hard time seeing any existing large code base work on Jigsaw.
Not any more. Requiring code modifications to use cross-module reflection was too painful and was dropped in the most recent Jigsaw iteration. You can reflect across module boundaries without problems now.
Just as a heads up; Jigsaw (as it is today) doesn't have versions, so the issues you describe won't happen. There will be one global json-lib module that will be available to all modules.
They've taken enough to get to this point that adding version numbering isn't going to happen, but it doesn't rule it out adding it in the future. They did the minimum necessary to split out the Java libraries into different modules but no more.
If you want to have versioned dependencies, you have to work with a module system that understands versions, like OSGi.
Yeah, Jigsaw will provide the base primitives which will allow what I described to happen. But it's up to the Java ecosystem to create or update the dependency layer above it. I'm assuming Maven will, but if they don't this is an opportunity for another dependency system to replace it. I think fixing the version conflict issue is enough of a killer feature to overcome even something as entrenched as Maven. I'm hoping Maven keeps up with these changes because I really don't want to rebuild existing build systems.
Not sure about Maven, but Gradle has already introduced a "software model" feature which is meant to map almost directly to Jigsaw modules. So the idea is you'll configure the module system through the build system, and it'll generate the right Jigsaw data for you. It also handles versioning and other things Jigsaw doesn't do directly.
But will Gradle's "software model" be compatible with Java 9's? Gradle's already incompatible in that it uses Apache Groovy instead of Java 8 for build config files.
I am 100% sure Jigsaw will not let you to do that stupid thing. Import statement has no version information, so your program will load json-lib 1.0 or 1.2 and then random errors will start to happen. It's called Dependency Hell: https://en.wikipedia.org/wiki/Java_Classloader#JAR_hell
Jigsaw will not let you do it in a vanilla configuration, but does allow for layers which do enable this. There is recognition that a single program should not hit this scenario but that app servers and similar may need to support it.
It's not really only app servers and other plugin systems that need this. Dependency conflicts happen routinely when building all kinds of Java apps, just by depending on useful open source libraries. This is one of the pieces of feedback I sent to the Jigsaw team and I'm glad to see it appeared in Mark's list of issues to consider.
Gradle's dependency tools help, but the best it can do is either flag an error or automatically de-conflict modules by always picking the newest version. If the version isn't fully backwards compatible, you can get deadlocked.
I'm torn on this. On one hand the sort of multiple version support offered by OSGi can be very useful, but equally debugging and coverage tools can quickly become confused because they may not cope well with multiple classes with identical names, and that ignores the fun of conflicting native libraries.
So for the first version I'd be happy to see this left to frameworks sitting above the module system, but I can appreciate other view points.
That is something completely different. The Jigsaw referred to in the title is the Java module system that will be part of Java 9, not a GUI browser made by a different group.
For ten years, the team who produce Java have been trying to modularise Java. Time after time they've run into big problems and the project has delayed or shelved. I hope, finally, they manage to succeed this time.
It seems adding modularisation to a product of the nature and scale of the Java API, while maintaining backward compatibility, is very hard.
Not really; a module system that has versions allows you to define dependencies in terms of version ranges, so that if installing a newer version into your app the module can decide in its dependencies if the version is compatible or not. If you are spinning up different names for each module/version then you have to go round updating all your code that depends on the module to use the different name, and you can't select a different one. The point was that Jigsaw doesn't have a concept of version numbers in its module dependency system; they are all dependent upon exact name only.
First, I am worried that instead of being able to just assume that "all of Java is there", there will be "no we just did a minimal install". Second, after watching the video briefly, we may already have tools for most of what this tries to solve (Maven, Spring boot, etc). Third, I suspect that there's some sort of nefarious scheme by Oracle to start charging for "premium" parts of JVM.
My initial feeling: it works just fine now, don't fix it. Or maybe I am wrong and it will be great.
Of special note is Springs need for optional dependencies. Previously several other projects requested this but always got shot down by Oracle with "we didn't find any need for this in the JDK". AFAIK optional dependencies are still not planned.
In addition the SWT/AWT Bridge that Java Mission Control which ships with OracleJDK uses requires special JVM flags to run with break up modularity. I'm not aware of any plans to fix this.
Probably the neatest part of Jigsaw is not the actual module system itself, but the tools it makes possible, specifically the "jlink" static linker. Jlink creates custom JRE images that:
• Don't have unused modules
• Don't use JARs as a format, instead using a much more optimised internal binary format
• Have various whole-program optimisations done on them, like removing the use of reflection.
• Can produce native Mac/Win/Linux installers/packages.
The last one is already a feature of Java 8 via the javapackager tool, but jlink makes it a much more powerful system.
45 comments
[ 3.6 ms ] story [ 130 ms ] threadThe primary benefits are better security, encapsulation and the jlink tool that lets you build standalone app-specific bundled JREs.
For example, I'll no longer be including the useless (for most Java apps) CORBA capability with my product. A server-side product will be able to exclude the desktop GUI API (AWT and Swing).
That is very unlikely. If you look at the java.desktop module (where things like AWT and Swing are) there are also tons of other things there like Java Beans. A lot of Software requires Java Beans at least indirectly (eg. Spring requires Java Beans). In addition there's the following dependency path. java.xml.ws -> java.xml.bind -> java.activation -> java.desktop A server side product is very likely going to require at leat one of these. The fact of the matter is that the JDK code is simply not modular enough.
What bothers me more is that things like Java Beans are in java.desktop.
Currently if you want to deploy software running in the JDK, you're forced to pick up the whole JDK, which is terrible if you want to deploy as small a codebase as possible, especially because literally nobody is using Swing and AWT and Nashorn in server-side environments.
Meanwhile, currently if you want to use a module system that only deploys code you're actually transitively dependent on in Java, you have to roll your own with its own concept of dependency and versioning.
Meanwhile, currently if you want to depend on a library that's already deployed on a host, you get to discover it via the classpath mechanism, which has an element of.. randomness.. to it, and in some cases if you have two versions of the same class in your classpath you can get some very strange and hard-to-debug behavior. (I've had colleagues who wrote custom classloaders purely to work around this in the constraints of our dev environment) This combines especially badly with the ubiquitous use of 'discovery' mechanisms in enterprise Java such as static logger binding or classpath-scanning for annotations to find configurations and bean definitions.
Meanwhile, currently, the 'public' designation in a module means public to everyone in every module, and if you want to avoid that and go package-private or less, you have to be private even within other packages of your own module, since package-private is not inherited by subpackages (com.me.x and com.me.x.y do not actually 'inherit' in any sense). That is, there's no distinction between 'public' and 'exported' types.
Jigsaw attempts to address all of these. I haven't followed it closely enough to comment on whether I think it's the ideal solution, but, it's definitely the right direction if Java is to continue being used everywhere - which it is, because it's deeply entrenched and (while not as modern as some would like) it's getting the job done.
Java currently doesn't have true packages. There's namespacing (com.companyname.abc.xyz), but it's all on a single classpath (java -cp). Dependency management like Maven gives somewhat of an illusion of packages. The end result of a Maven build is still a bunch of jars running with "java -cp".
For example, in Maven, imagine there's a json-lib 1.0 and 1.2. Library A needs json-lib 1.0 and Library B needs json-lib 1.2. Project X is using both Library A and Library B and when Maven tries to build, there will be a version conflict between json-lib 1.0 and json-lib 1.2. There are no good options at this point because the single classpath forces the selection of one version for json-lib. The developer has to either pick json-lib 1.2 and hope Library A can run with it. Or pick json-lib 1.0 and hope Library B can run with it. This is assuming Library A and Library B are external libraries that the developer has no control over and hasn't been updated in a long time.
With packages (Jigsaw), it's possible to let both versions exist in a project. It will be possible for Library A to be a package and use json-lib 1.0. And Library B will be another package and can use json-lib 1.2. During runtime, each package will have an isolated classpath and so the dependencies won't conflict. I'm assuming the Maven developers will update Maven to do this once Java 1.9 is released.
This will remove a big headache that currently exists for Java developers. The chances of a version conflict approaches 100% as the number of dependencies grows in a project.
The other thing that Jigsaw is bringing is modularizing the standard library as well. So if you don't want CORBA in your runtime image than you can leave it out.
And isn't that classloader magic?
Perhaps ignorance on my part.
Everyone rallied against OSGi because the strict modularity showed developers that in general their application wasn't as modular as they thought it was; and the fact that class loaders enforced that permissioning model showed where random Class.forName and module busting code lived.
Guess what? Those developers will have exactly the same problems with Jigsaw modules.
What Jigsaw will do is educate Java developers that the pain points are in strict modularity rather than any one module system.
And many more. Jigsaw also locks down reflection. In addition Jigsaw lacks many work arounds that OSGi has to get software working (fragments, buddy classloading, dynamic imports, optional dependencies, capabilities, …).
Honestly I have a hard time seeing any existing large code base work on Jigsaw.
They've taken enough to get to this point that adding version numbering isn't going to happen, but it doesn't rule it out adding it in the future. They did the minimum necessary to split out the Java libraries into different modules but no more.
If you want to have versioned dependencies, you have to work with a module system that understands versions, like OSGi.
Gradle's dependency tools help, but the best it can do is either flag an error or automatically de-conflict modules by always picking the newest version. If the version isn't fully backwards compatible, you can get deadlocked.
So for the first version I'd be happy to see this left to frameworks sitting above the module system, but I can appreciate other view points.
https://www.youtube.com/watch?v=y8bpKYDrF5I
It seems adding modularisation to a product of the nature and scale of the Java API, while maintaining backward compatibility, is very hard.
First, I am worried that instead of being able to just assume that "all of Java is there", there will be "no we just did a minimal install". Second, after watching the video briefly, we may already have tools for most of what this tries to solve (Maven, Spring boot, etc). Third, I suspect that there's some sort of nefarious scheme by Oracle to start charging for "premium" parts of JVM.
My initial feeling: it works just fine now, don't fix it. Or maybe I am wrong and it will be great.
http://openjdk.java.net/projects/jigsaw/spec/issues/
Of special note is Springs need for optional dependencies. Previously several other projects requested this but always got shot down by Oracle with "we didn't find any need for this in the JDK". AFAIK optional dependencies are still not planned.
http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-Decem...
In addition the SWT/AWT Bridge that Java Mission Control which ships with OracleJDK uses requires special JVM flags to run with break up modularity. I'm not aware of any plans to fix this.
Modules are not allowed to export the same packages.
• Don't have unused modules
• Don't use JARs as a format, instead using a much more optimised internal binary format
• Have various whole-program optimisations done on them, like removing the use of reflection.
• Can produce native Mac/Win/Linux installers/packages.
The last one is already a feature of Java 8 via the javapackager tool, but jlink makes it a much more powerful system.