Something not mentioned amongst the JEPs on the release email is that this release also fixes a bunch of issues related to running the JVM in a container. I wrote about some of these yesterday:
Some support for these was also introduced in JDK 8u131 back in April 2017 [0]. Do you know if these issues are the same ones fixed in JDK 8 or maybe they have now been backported to JDK 8 and 9?
JDK 8u131 and 9 had a few improvements but the changes to 10 increase support.
For example, 8u131 and 9 only supported cpu sets whereas 10 includes support for cpu shares. Available memory detection in 10 applies to the whole of the JVM rather than just the heap on 8u131 and 9.
Makes sense, thanks a lot for the insight. I've seen some comments on the JDK 10 issues pushing for a backport to JDK 8 and 9, let's hope they are eventually backported!
I'm so confused, I didn't even know JDK9 was out yet!
Reading elsewhere they are apparently moving to a 6 month release cycle.
For people using Java in businessey environments, I'd love to hear your thoughts on this. Do you think you'll be able to keep up with the JDK changing twice a year? When I was in this game we were always on versions that were years behind, but maybe this has changed.
This release cycle makes no sense to me. We haven’t even finished migrating all our components to compile with JDK8 yet, though they’ve all been running against it for a while now. We’re barely even discussing moving to JDK9 at this point. What company with a reasonably large software base is going to keep up with a six-month release schedule? Java isn’t a web browser or some other user application. Who would even _want_ to spend the kind of resources required to constantly be testing new JDK releases?
>This release cycle makes no sense to me. We haven’t even finished migrating all our components to compile with JDK8 yet
Why is it Oracles fault that you keep your components on Java version that has been deprecated and support dropped 4 years ago?
>What company with a reasonably large software base is going to keep up with a six-month release schedule?
What? No. That's now how it works. Every 3rd release is LTS and it support time is between 6 and 11 years as so far discussed. Java8 won't be supported after January 2019, Java11 (LTS) will be release in September this year.
> Java isn’t a web browser or some other user application. Who would even _want_ to spend the kind of resources required to constantly be testing new JDK releases?
You're not supposed to be testing it. You're supposed to write code to a contract, contract won't or shouldn't change. If you write code that follows implementation instead a contract (let's say you relay on HashSet order - I've seen it), it's your fault. We always make sure we write code that follows the contract. We're migrating our code base to Jigsaw now, after Spring 5 and SpringBoot1.5 were release with updated dependencies. If Spring and Tomcat teams made it available earlier, we would be on Java9 months ago.
Linus may be occasionally obnoxious but I believe his "don't break user space" mantra is a significant reason why Linux is so popular. A similar attitude guided Windows development (until Vista) and it dominated the desktop world. In comparison your attitude seems user hostile to me. No "user" is interested in comparing theoretical specs with the behaviour of the reference implementation. They just want a tool to deliver solutions that work.
For the first time in years, I'm looking at alternatives to Java for my next project. Java was always seemed to offer a pragmatic compromise in terms of language design and features and the availability of developers and libraries. Rapid breaking releases destroys most of the value of Java for me.
>Rapid breaking releases destroys most of the value of Java for me.
Almost nothing is broken in Java. Jigsaw modified who to use reflection to access data in an insecure manner. You should not be doing that in the first place for obvious reasons. But the code that was using reflection still works, you just get a warning when starting an application. That's all.
>No "user" is interested in comparing theoretical specs with the behaviour of the reference implementation
So you're probably not going to write any code in any strong-typed programming language, all of them have some kind of contracts you should/have to follow.
Do you know that Oak source code (what Java was called before) still compiles and runs in Java10?
I'm not sure how you can confidently assert that "almost nothing" breaks with Java 9. Maybe we were just unlucky that the very first application (a simple less than 20KLoC JavaFX Gui) we used to test upgrading to Java 9 broke immediately. But actually googling "Java 9 breakage" returns a ton of results so I guess our experience wasn't an outlier.
You are just repeating that it's fundamentally the user's fault because they "should not be doing that". A properly designed tool prevents incorrect usage. If a version of Java allows you to do something and that something proves to be very useful to GET THE JOB DONE, then I'm with Linus - the blame is not with the user.
For example, there was simply no alternative to using Unsafe in the past to get reasonable Java performance for certain task. The fact that it was there allowed me to resist the pressure to move a significant part of our codebase to C++. Of course we "should not be doing that" (using Unsafe) but the alternative was abandoning a large existing code base and hiring a bunch of C++ experts or retraining our existing developers or spending 10 times as much on our server capacity. Using Unsafe was a simple pragmatic decision. You cannot say it was "wrong" without knowing all the factors that went into the decision.
There are long term support releases. I suspect that most enterprise places will end up using only LTS versions.
The real killer with the six month releases is not that they're every six months. That's doable. The killer is that they have zero support (even for security issues, I believe) once the next release comes out. As a result, you have to be ready to switch immediately. If you could upgrade to Java 10, then wait twelve months and go to 12, it would be less painful.
Yeah, the lack of overlap in support between LTS releases is the real killer. I predict that in 5 years there will be few people using the Oracle JVM. People will migrate to the JVM supported on their OS (for example, RedHat supports OpenJDK for the life of the OS as part of their OS/middleware offerings).
If I read that correctly, the “breakage” is a bug fix, as that particular Java 7 compiler isn’t behaving according to the spec. You can argue that breaks backwards compatibility, but in the smallest, most innocuous way possible.
My understanding after reading the answer to that SO question is that the behavior in 7 was a bug. New releases of javac aren't required to be bug-compatible with previous releases.
> In comparison your attitude seems user hostile to me.
Who care about his attitude? Is he the BFDL of Java or something? :)
On a separate note, good luck moving away from Java to a platform with better backwards compatibility! There's a reason Java is used for enterprise software, it's one of the best platforms for keeping compatibility. It's probably not perfect, but the others are just worse :)
I guess he cares (he spent the time expressing it in writing) and I care (I took the time to respond) :)
Also I'm not considering alternatives just because Java 9 broke stuff. There are lots of other reasons why Java irritates me but I felt it was still a winner when you balance up all the factors. But if backward compatibility is no longer going to be prioritised, then this shifts the calculation so that it's at least worth it, in my mind, to evaluate alternatives. So we're going to try Kotlin on a fairly small self-contained project.
"Contract won't or shouldn't change" seems unrealistically idealistic to me. Java migration - or any platform for that matter - is not just migrating its language features but also its ecosystem - runtime, VM, GC, frameworks.
There are many examples of migration problems for any platform - just have to google it. When information that can challenge our assumptions is just a google search away, I don't see why one should hold on to blind faith in idealistic assumptions. Here's one writeup of a system whose performance suffered simply by migrating to Java 8 without involving any code changes [1].
Enterprise Java is mostly about writing glue code that combines dozens of libraries and frameworks. How can you tell (without testing) if tens of millions of lines of code in those libraries are not doing anything stupid, like depending on implementation instead of contract?
The most important contract, the JVM spec, is really good in Java, and that makes up for almost everything. Javalang and the standard library is generally very good about maintaining backward compatibility (almost to a fault, some would say). Of course, there is code in the wild that depends on, for example, the com.sun packages and so on, and that extend the JVM using JNI - in those cases, all bets are off. But that was always true, and I'd argue that such contortions are generally as ill-advised as they are rare.
So, yeah, I think a faster release cadence is a good idea! Upgrading the runtime should be as simple as upgrading any other dependency.
This is my only problem with it. I can’t imagine it stays like that. I feel like there has to be at least a year of overlap between release of one LTS and deprecation of support for the previous one. Or at least a commitment to continue with security patches for longer (while stopping bug fixes and enterprise support)
You'll be OK as long as you're dropping off suitcases of money at Oracle's door, but currently it appears that freely available fixes/security updates will cease as soon as the next LTS is released.
If that were so simple. What if your software gets deployed on an application server? If you upgrade, you need new support contract, this costs money plus leads to possible deployment/config changes, for instance going from JBoss 5 EAP to JBoss 6 EAP is not a pleasant experience as almost all configuration was radically changed.
What if part of your application is audited and certified by some regulatory body, when you upgrade, you need to go through the process again.
Java value is stability, you can assume your software will run for 20 years without touching it.
No one is forcing anyone to upgrade. What worked on Java 8 3 years ago, will work on Java 8 in 17 years. If your team have extra requirements (audit, certification etc.), it seems it sells enterprise software. All those things cost money, but I assume you also charge money. So, what's exactly the problem? It is a bit naive to expect to get ultra stability for free from your suppliers, but charge top dollar from your customers...
By only providing fixes and security patches for a few months -- after that you need to move to the next version (with all that entails testing and adapting wise for large codebases), or you pay for enterprise support and get support for years.
Before you could go to any version and expect it to be supported for years.
Now, if you dare go to some version above 8, you're supposed to either pay (for long term support), jump directly to the next version after a few months, or stay without security fixes.
Not sure that’s how it works. You don’t really need to update anything. Ubuntu runs on y monthly releases, for instance, and sees plenty of enterprise usage. The Linux kernel itself is updated as often, if not more. Google Chrome updates all the time. Ruby does yearly major releases, as do other languages. Go does six months, I think.
Teams in charge of software release whenever they want or can, clients are free to use whatever version whenever they want.
The problems only happen with breaking changes - and I haven’t seen a single case of Java breaking backwards compatibility (not counting cases where users intentionally used or relied on private implementation details).
If you have written your regular enterprise web service you will probably not have very complex code (I'm not talking about business logic, but language features).
But then you are using a 1 year old framework (if you're lucky) that depends on a version of library X that is 2 years old that depends on a 3 years old library etc.
At the end of the chain you have a library that does low level stuff (bytecode instrumentation for example) and is a few years old. That is what may give you problems, and often the only practical solution is to update to a newer version of the framework, which can be quite expensive.
I'm curious, how large of a company did you work for such that you were able to easily upgrade your JDK version?
Because I worked at a fairly large tech company and every one of our applications required some amount of manual intervention beyond figuratively switching all the "7"s to "8"s. That's despite the fact that hardly any of them were doing anything particularly complicated, and absolutely none of them were doing anything involving hidden com.sun APIs. I think it's just a consequence of such a large build system.
Yeah the reality of the situation is that it's never as straight-forward as just recompiling with the latest JDK.
From my experience it wasn't generally code written in-house that'd cause problems (but sometimes it was), it was dependencies and transitive deps that required the older JDK (sometimes they relied on old bugs or old tooling, sometimes they just couldn't be recompiled on the new JDK for whatever reason).
Build tools that relied heavily on JVM internals often couldn't upgrade for some time. Third parties integrating with your software and the new JDK brings a slight change in it's SOAP/XML/ser-deser stuff etc.
That said, Java has been the best at backwards compatibility that I've tried, given it's popularity, and most of the pain was in the early days (like anything I suppose, see the Javascript world atm). Microsoft's offerings probably do backwards compatibility well, but then you get all the rest of the technical- and wallet-pain that that environment brings with it.
For instance, if you depend on an old version of the Spring framework, using some Java 8 features (like lambdas) will break, since it generates bytecode Spring doesn't understand. Compiling as Java 7 prevents inadvertent use of these features.
Java 8 made some changes to type inference that can, in certain edge cases, cause generic method calls to bind differently. While it’s _mostly_ backwards compatible, it’s not entirely.
I think it makes total sense to have the language evolving on a scheduled basis rather than stagnate.
If your company is only discussing moving to JDK9 now, what difference does it make that JDK10 is out? If you are using the free version, there is no real support. If you are a paying customer, Oracle will support you to the end of time while wringing every last cent out of your company.
What difference does it make if the language keeps evolving? Do you expect the entire world to revolve around you and your company?
Given that your company is still on JDK7, and is already saying a "fuck you" to new features, I don't think anything will change for you at all. You can continue ignoring newer features, but that doesn't mean everybody should. If they find value, they should have an option to move fast.
This is the same strategy that wrecked Eclipse and Firefox. Every 6 months is just too quick for most people to feel comfortable, and will cause fragmentation as the 3rd party ecosystem updates things at different rates.
They broke compatibility with v57 exactly for that: to make continuous small changes. The previous situation was untenable since there was no API for extensions, the extensions could just go through Firefox internals and change at-will whatever they wanted.
The whole point of WebExtensions is that they won't need to break compatibility after this huge leap.
FireFox constantly broke all my extensions with just about every minor update. It was maddening. After being a die-hard FireFox/Netscape/Mozilla user since the 90's, I finally gave up a few years back and switched to Chrome. I can't recall a single time since then when my browser or extensions stopped working because of any update, not just a minor one.
I'm stuck with Java 8, because there's no 32-bit support on newer Oracle JVM and I have to run my code on Windows 2003 servers. I guess it'll be like Delphi 7, best version which will stick around forever. I, personally, don't care about updates. If something works, it'll work.
I think that if you still have Windows Server 2003 boxes (for which the official support ended 3 years ago) being stuck with Java 8 is the least of your problems...
We intend to only switch to LTS versions. 8 is LTS, as will be 11. We'll switch a little while after 11 comes out once we believe any release bugs are ironed out (7's release worried me).
Reading through the comments and I’m amazed how people are so darn negative to this. Most of the time people complain about how old java is and the are much more “modern” options. And now suddenly when they finally picking up the pace, you whine like bunch of kids that lost their candy...
It does not seem to be uncommon to recommend staying away from the non-LTS releases. It is probably not only up to you whether or not your software supports the next JDK release; all your tooling and libraries need to do so as well.
Does it actually help? After 10 years of java I don't really remember any case where defining local variable as final would catch an error.
Though maybe these cases are easy to forget.
I remember bugs that were caused by the exact opposite. If p is superceded by updated then it's not a good idea to have both hanging around in the local scope.
You shouldn't be able to doSomethingElse(p) when you actually mean to doSomethingElse(updated).
I don't know Rust very well at all, but I believe that Rust would only prohibit that if p and updated were referencing the same thing. If updated was a modified copy of p then I don't think Rust would help. But I could easily be wrong on that.
What would help is splitting the function up so that you don't have multiple named variables representing multiple versions of the same thing in the same scope:
Person doSomethingAndDots() {
Person p = doSomething(...)
...
return p
}
main() {
doSomethingElse(doSomethingAndDots())
}
Rust explicitly allows shadowing, that way you can have it both ways. An immutable variable that can't be reassigned but you can still reuse names.
That is to ease the pain of unwrapping nested types and error-checking intermediate steps so you don't have to come up with new names for each intermediate.
I really like being able to declare immutable variables with ‘let’ in Swift. Java should add the immutable option too. Although, ‘val’ makes more sense considering Kotlin and Scala use it.
For me, it is not about catching errors, it is about documentation.
In the codebase I work on most, all variables that can be marked final are marked final. That means that whenever I see a non-final variable, I know that something tricky is happening and I need to be extra careful in reading the code.
The problem is that java.util.Optional has no special syntactic support compared to the way optionality is supported in Kotlin for example. And it is barely used in the standard libraries. And many/most 3rd parties libraries don't use it. Thus you end up with multiple styles in your code base: in places checking for null, in other places extracting the value from an Optional. And the type system/language doesn't prevent an Optional reference itself being null.
The Optional class is typical of the halfassery that has accompanied many improvements to Java over the years. From java.util.logging to generics to streams, I'm invariably irritated by compromises particularly as they've decided that maintaining backward compatibility is now a secondary concern.
I've run out of patience in the direction Java has taken and I've been a user since 1.0.4 - I'm going to try Kotlin for my next project.
Also, if you're interoperating with Kotlin, a nullable reference works better than an Optional. A Kotlin nullable reference compiles down to a reference with intellij's @Nullable annotation, and a Kotlin non-nullable reference compiles down to a reference with intellij's @NotNull annotation.
It also works in the opposite direction: a Java parameter or return value annotated as @Nullable (doesn't have to be intellij's, the Kotlin compiler understands several annotation libraries) will appear as a nullable reference to Kotlin code, and a @NotNull or @Nonnull annotation makes it appear as a non-nullable reference.
Coming from functional languages, I really really tried to make optional work in our code base. However, it's inability to interact with checked exceptions or even slightly unusual control flow make it a real pain. It feels like fighting the language. My current suggestion is to pick a nullability annotation, and then wire it through your compiler and IDE, so it tells you if you forgot null checks, or made a superfluous null check on something annotated non-null.
I was surprised by the responses about Optionals. Will have to look into it. As an alternative I have been looking to use the following to guarantee that certain methods cannot/will not return null (below). Maybe that is the better way to go?
I think they meant the separate keywords to distinguish "var" and "final var". Personally I like just reusing the final keyword, which for once would actually mean the very same thing in the very same place, with "var" just taking place of the type name. More familiarity, less surprises.
I would argue it's not about the extra characters, it's about enforcing explicit mutability.
In Scala, where var/val both exist, each time you declare a variable you are forced to think about its mutability. But if you only have "var", with the _option_ of tacking "final" to it, then a programmer can simply forget to make that decision, because the language allowed them to.
Those "6 extra chars" mean more noise for human on the screen, it can lead to line wrapping or in other way harm the formatting, and last but not least it does not make it easier to promote good coding practices.
If the final keyword hadn't existed before I'd agree, but it does exist, does exactly what you'd expect it to here, and I'd argue that since it's consistent with how it used to work, is actually easier to understand and grasp. Local type inference is a new feature. Locals that can be assigned once is not and people are already familiar with how such locals are declared. And there's no ambiguity which variant is the correct one, e.g.:
var i = 0;
final var i = 0;
int i = 0;
final int i = 0;
val i = 0;
One of the options there is a very odd one. And if there was "val", would "final var" be disallowed?
None of course, but I think that's the point of the complaint. For a feature supposed to increase convenience, it didn't go as far as it could have. Still, I'm glad var is in there. (Now, my employer just needs to get off of Java 8...)
var seems like a bad idea to me. One of the things I like about Java is (strong?) typing. Recently learning C# and was put off by 'var'. Why is it a good idea?
'var' in C# and Java doesn't change strong or static typing at all. It's just type inference. Your code is still statically typed, the compiler and IDE will catch errors. It's just that it's smart enough to infer the types of redundant things instead of making you type it.
So instead of typing:
AbstractConcreteFactoryFactory factory = new AbstractConcreteFactoryFactory();
You can just type it only once:
var factory = new AbstractConcreteFactoryFactory();
`Simple<List<Map<String, Demo>, OtherList<Map<Int, String>>` is a little bit painful.
I use scala and basically most often at least public Methods should (in scala you can omit even that, however some functional libraries need a return type) have a explicit type, which most often is enough.
I'd advise spending an afternoon trialing Kotlin. It works side by side with existing Java code, has good IDE support (*assuming Jetbrains), and gets you var/val along with a lot of other goodness (data classes, extension methods, etc). At worst you'll have a nice demo for your next tech all-hands.
How does Class-Data Sharing – which they've now extended to include application classes – interact with the new "jimage"-format files (e.g. lib/modules) introduced in Java 9? Will the jimage file also be efficiently memory-mapped, making CDS superfluous, or should they be both be applied?
There is disappointingly little information available on jimage so it's hard to compare. jimage does require you to be fully modular while CDS does not. OTOH CDS is quite a bit tedious to set up.
I'd be really interested to know if there are folks out there who enjoy Java programming as compared to the alternatives out there today.
Does Java fill any kind of niche aside from maintaining those gargantuan projects that are typical of governments and large corporations?
When I learned Java in the 90s, it was hyped up with the promise of microwaves and refrigerators and televisions and every little thing running Java software.
Instead, the only time I've found myself turning to Java was when I built an IDE on top of eclipse for a custom programming language, a few android apps, a few swing projects for school, and a few socket based projects. When dealing with IOT and smaller hardware, I've found myself using node(js) instead.
I've rarely ever found it enjoyable. The IDEs have been sluggish, the GUI libraries have felt cheap and unpolished, with those clunky diamond shaped radio buttons, and I always found myself writing too much code to do very simple stuff, because every library was wordy and verbose. When I looked at my work, it felt inelegant and cumbersome.
What is Java like in 2018? Are there any good, polished open source projects that work well ? What would make you look at a project and say "I think Java is the most suitable choice for that" today?
Some parts of Graal (like ahead of time) were added in Java9 on Linux 64bit, rest of the Graal was added to Java10, but also only for Linux 64 bit. Graal is pretty much workable but there are some edge cases that crash your code or the JVM, eg. Ruby generally works, but Ruby on Rails doesn't.
what about OpenJDK with OpenJFX?
Building by myself it's an overkill task (it requires Qt for Webkit), especially on more platforms. I think it's a pity there are no public available releases of OpenJDK with included JavaFX out there.
When Oracle will remove it in Java11, it would be even worse
I agree this is something which should be prioritized, but I don't necessarily think the answer should be to just provide pre-built binaries. I feel really uneasy about open source projects that are almost impossible to build by anyone by the authors - more work should go into making the build process less obscene.
https://www.opsian.com/blog/java-on-docker/
Relevant JEPs:
https://bugs.openjdk.java.net/browse/JDK-8146115
https://bugs.openjdk.java.net/browse/JDK-8179498
https://bugs.openjdk.java.net/browse/JDK-8146115