IBM and Red Hat to Vote “No” on Java Modules (Jigsaw)
infoq.com
infoq.com
Despite all the breakage, Jigsaw still totally punts on the problem of versioning. So, all it lets you do is declare that you need something (with a self-destructing opt-out); but it still doesn't solve the problem of two libraries requiring two distinct, mutually incompatible versions of the same library.
Producing clever vendoring tricks in build packages would solve actual problems that Jigsaw doesn't even begin to address. Until then, the added value seems pretty questionable.
There are a lot of nice things happening in JDK9 that just makes everything a little bit better as if by magic, and they're being held back by a standard that breaks stuff and ostensibly few people want. That doesn't mean the exercise was futile; the source code reorg is probably an improvement regardless.
Good to hear. It takes a surprising lot of backbone to resist the call to "just do" tortured things to fix a problem--sometimes I play the bad guy, saying "no, that's stupid, figure out a better way" but yet we see repackaged Java classes shipping here and there...
That's not abusing the classloader; it's using the classloader.
> and at Google we completely ban it for Java
Yeah, I'll sure to listen to Java tips from the developers of the Android API.
That upgrade wouldn't happen, or it would be really nasty. I'll rather tolerate a standard library with a lot of bollocks in there and provide security around it.
import *
to just grab everything, like we're all doing right now. Going and adding a single line to a few hundred build.xmls doesn't sound excessive. shrughttp://javaposse.com/java_posse_259_jigsaw_and_jsr_294_inter...
Some of these libraries take more disk space than the frontpage of a news website in the browser cache!
And I feel obliged to use them sometimes lest they turn into malware out of sheer boredom.
(Plus, of course, rt.jar isn't so bad if you can share it in a layer :))
Except Jigsaw does nothing to fix this. Your webservice framework depends on jaxb which depends on activation which depends on JavaBeans (everything depends on JavaBeans). Turns out JavaBeans is in the same module as these GUI toolkits.
Reading that proposal I can see that Jigsaw has run up against and is trying to 'create' some (but not all of course) very similar features on which to host a module system. And some of the very same arguments come up against them.
In particular this statement from the recommendation[1]:
Jigsaw's implementation will eventually require millions of users and authors in the Java ecosystem to face major changes to their applications and libraries, especially if they deal with services, class loading, or reflection in any way.
Is nearly a word for word echo on the reasons why my 'overly complicated and invasive' security requirements would all the people writing Java code that really didn't care all the much about such strong security guarantees.
I don't have a position one way or the other, I've been out of the Java world for a long time now, but it really struck me like Deja Vu to read that objection.
[1] https://developer.jboss.org/blogs/scott.stark/2017/04/14/cri...
One of my clients is apparently friends with Mr. Gosling and was surprised when I recognized him from a photo at a Sharks game in the "oh wow! That's James Gosling". Never met, just from having read a wikipedia page.
Concerns Regarding Jigsaw(JSR-376, Java Platform Module System) https://developer.jboss.org/blogs/scott.stark/2017/04/14/cri...
"Following links with enticing sounding names like “Where to start” simply gives you a bunch of links to off-site tutorials written by implementation vendors, none of which are any good. There is also a list of five different books on the topic. This developer experience is not excellent. But mostly it’s complicated because its design is genuinely enormous."
Five books? That's horrible.
(By way of introduction, I've spent a good deal of time with OSGi and none at all with JBoss or Jigsaw. I am more-or-less out of the Java environment at this point.)
Ok, here's the deal: OSGi looks big and complicated. Part of that is due to the fact that it's been around for like 20 years and part is due to people trying to do fancy things with it in the Java environment, where everyone else is trying to do fancy things with basically incompatible magic. (Virgo[1] waves desolately from off in the distance.)
[1] http://www.eclipse.org/virgo/
In reality, OSGi isn't that bad. I learned it mostly from reading (part of) the spec, which isn't the worst as far as specs go. OSGi is fundamentally a generic container; if you're familiar with servelet lifecycles and have used Tomcat to deploy and undeploy web apps, you're familiar with about 60% of OSGi, which is a subset of that. The other 40% of OSGi's fundamental complexity is built around the sole purpose of allowing an application to depend on a library A, which in turn depends on version X of library B, while at the same time the application depends on library C, which itself depends on version Y of library B. (The other 10% of OSGi's fundamental complexity is the "services", which are double-plus fun extra features that make life better in many ways. But we can ignore them here since we're talking about modularity.)
Doing that sort of thing is hard. Doing that in Java, where everything uses reflection, dynamic code generation, and classloader magic, is not so much hard as terminally bizarre.
Personally, I view a module system as an aid for the programmer: it prevents stuff that you shouldn't touch from leaking into stuff that you should touch. As a result, both OSGi (and, I think, Jigsaw) fail badly as module systems: If it waits until runtime to blow chunks, it's not helping the programmer. But, in the Java environment, modularity in my sense is impossible. (It's also unwanted, but that's a rant about Java developers for another day.)
Anyway, when you say, "oh, they're just whining that their system didn't win", you are right, sort of. But on the other hand, "their systems" have spent a long time dealing with the insane, Sorcerer's Apprentice-type nuttiness that is the rest of the Java ecosystem, and it appears that Jigsaw is just ignoring that nuttiness, that the majority of Java programmers use, and enjoy, every day. Which was the major worry from the OSGi community when the Jigsaw project was announced.
As an amusing aside: version numbers. OSGi has a moderately complicated semantic versioning [2:PDF] system to support that fundamental goal up there. OSGi version numbers look like major.minor.micro.stringy, with specific rules for bumping the major, minor, and micro numbers. Jigsaw originally started out with an incompatible version number format, apparently due to the fact that Java versions have a fixed constant major number of 1. The current [State of the module system] for Jigsaw says,
[2] http://www.osgi.org/wp-content/uploads/SemanticVersioning1.p...
> A module’s declaration does not include a version string, nor constraints upon the version strings of the modules upon which it depends. This is intentional: It is not a goal of the module system to solve the version-selection problem, which is best left to build tools and container applications.
The Jigsaw requirements[3] go further to say,
> Multiple versions — It is not necessary to support more than one version of a module within a single configuration.
> Most applications are not containers and, since they currently rely upon the class path, do not require the ability to load multiple versions of a module. Container-type applications can achieve this, when needed, via dynamic configuration, as outlined above.
> Version selection — The process of configuring a set of modules need not consider more than one version of any particular module.
> In other words, this specification need not define yet another dependency-management mechanism. Maven, Ivy, and Gradle have all tackled this difficult problem. We should leave it to these and other build tools, and container applications, to discover and select a set of candidate modules for a given library or application. The module system need only validate that the set of selected modules satisfies each module’s dependences.
[4] http://openjdk.java.net/projects/jigsaw/spec/reqs/02#non-req...
Therefore, Jigsaw is explicitly free to be incompatible with OSGi or any other existing container system. Yay.
TL;DR: It's not so much that someone else's system didn't win, but that Jigsaw doesn't care that Java is a big, giant, hairy bundle of nasty and that fact is likely to make everyone's life harder.
P.S. For OSGi information, I strongly recommend Neil Bartlett. His OSGi in Practice and blog posts are exceptionally good and he is very helpful and friendly in the OSGi community, as I recall. He's also on the Jigsaw experts group. And one of the Concerns regarding Jigsaw contributors.
For my applications I see some value in Jigsaw specially modular images. Despite being available for long time OSGi still is some esoteric technology without mass developer appeal whereas Jigsaw seems to have potential to be really useful to lots of developers.
It is rather sad that OSGi people keep piling on Oracle for not using their barely successful technology.
The down side was that OSGi requires modularization, which exactly no Java developers to my knowledge had any experience with. Plus OSGi modularity is entirely done at runtime and Spring's tooling to try to support it was incredibly flakey. Conversations went like:
"My app works fine on my dev box but blows chunks when I try to deploy it."
Me: "You have to be explicit about whay you are depending on in your app's manifest."
"I see your lips moving, but all i hear is barks, grunts, and squeals."
"Sigh. I'll fix it."
I can't really see jigsaw making the situation any better, especially since it explicitly ignores versioning and containers.
Especially of interest is this introductory video: https://www.youtube.com/watch?v=2Hmrn_r-uJA
Java has an incredible open source community and there are amazing high-quality packages available to solve any problem under the sun; and so it is common for Java apps to have large dependency graphs. For example, take Google Guava, a popular and powerful Java library. It's so useful that other libraries depend on it. Let's say that our application uses two libraries called Component-A and Component-B, which both depend on Guava. However, Guava is constantly changing, and so it may arise that Component-A depends on Guava version 17 while Component-B depends on Guava version 20.
This is called a version conflict, and Java packages aren't enough to solve the problem well, though module systems can. For example, a module system allows you, as the application owner, to override the Guava version used by Component-A, replacing Guava-17 with Guava-20. If Component-A is compatible with Guava-20, then that resolves the problem. Another solution module systems provide is to allow both Guava-17 and Guava-20 to coexist in the same application, used separately by Component-A and Component-B. If those components are using Guava 'privately', as part of their implementation only, then this might also be an adequate resolution.
The default Java package system does not have a notion that there may be multiple implementations of a class like `com.google.common.base.Preconditions`, and that you may wish to select one version of it or another, or that you may want to use different versions in different parts of the application. It's not normally desirable to tamper with dependency versions or load multiple versions simultaneously, but version conflicts happen and module systems give you tools to deal with them when they occur. Fortunately, the behavior of Java packages is determined by Java ClassLoaders, and module systems can implement their own ClassLoaders to provide dynamic behaviors like these that go beyond vanilla Java's capabilities.
Since Java supports reflection, with regular Java packages, any class can access any other class and class member in the app, regardless of whether it's package private. These reflection capabilities are super useful; they're what enable frameworks like Spring, Guice, EasyMock, and Jackson. However, unrestricted reflective access is also a liability (viz. Ruby Monkey Patching), and it's something that you'd prefer to outright disable or at least sandbox in most components you depend on. But since these components might legitimately require reflection in their implementation, like using Guice for dependency injection or EasyMock for testing, you may not be able to disable reflection entirely; instead, module systems can help you sandbox reflection so that it operates within the confines of the module, to make the system simpler and more predictable.
Some module systems like OSGi also extend into the runtime behavior of your application, and help you manage complex applications. Certain very complex Java applications act a bit like an operating system: there are multiple services within the app that communicate with each other, and the module system isolates them for encapsulation reasons, loads them in the appropriate order, connects them together through exported interfaces, and provides management actions like reloading a module while the rest of the app keeps running. These module systems are for Java apps what systemd is for Linux (including the fact that some people love them while others think they're overly complex and should be avoided).
Some of these purported issues with Jigsaw appear to be quite complex and a bit difficult for the layman Java user to understand.
Jigsaw totally punts on the problem of incompatible versions. In fact, it just doesn't do dependency versioning; only module versioning.
I am going to sully it by weighing in with my opinion:
> Java packages are a fine "module" system if you're designing a single large cohesive application that has no dependencies or trust boundaries.
I've always thought that Java packages are a fine module system period. They require library authors to be prescient enough to never make backward-incompatible API changes (it's easy, just make a new package any time you want to change your API in an incompatible way).
Obviously, the open-source community has fallen down on the job in this respect, and I'm sure there is a widespread opinion that the burden of managing API changes in this way will never be met and so something like Jigsaw is necessary.
But I think the required culture change among library authors would be much preferable to adding the complexity of another module system on top of packages. And it's such an easy change for library authors to make to their behavior that there must be at least some hope of being able to reach a consensus around it.
No upgrade path from JAR files, the most common packaging system for Java?!? That sounds like a good enough reason for me to dislike it.
I watched a whole hour and a half presentation on it, and the time was well necessary to explain the way things work and outline a migration path for existing code.
The worst thing about it: I can't remember much about how it was supposed to work. I just remember that it was highly unintuitive, requiring both explicit imports and exports in specific files for each module.
The fact that it is so tightly coupled to JDK refactoring also gives me pause. Seems like a design overfit. Both concerns should be handled separately.
Sure a module system can help to separate out the JDK libraries, and that's certainly a nice way to check you've achieved your objectives with the design. But when this refactoring itself is one of the major justification for the design, something is wrong.
Red Hat has a great Java alternative in Ceylon with a module system which seemed far more sensible when I read about it (you should take this observations with a grain of salt and check for yourself, I'm going on hazy memories).
I guess rewriting all your code is one thing but rewriting it under the assumption of concurrency is just a bridge too far.
I think you might be thinking that the impediment to removing the GIL is user code. It is not. The impediment is that CPython - the standard Python runtime - was designed around using the GIL, and it's extraordinarily hard to remove it and still meet the existing single-thread performance goals. There are also ancillary issues surrounding user code - particularly modules written in C, I believe - but the runtime itself is the biggest issue.