Hi, My name is Carl and I'm a software engineer and aspiring artist.
Over the past two years, I did something no one thought was possible. I updated our code from JDK 8 to JDK 16. Out of all the things I’ve accomplished at Netflix, this is the one thing I’ve had the most questions about, and the most astonishment. “How did you do it?”
//在过去的两年中, 我做了件没人觉得可能的事, 我把我们的代码从JDK8升级到了JDK16. 在我在网飞达成的许多成就中, 这是我被问得最多的, 最令人惊讶的一个. “你怎么做到的?”
If you aren’t familiar with Java, Oracle made a tough decision to modernize Java. Prior to Java 9, a major version came out once every few years, and with relatively minor breaking changes. All that changed in Java 9; major versions were going to be breaking, and coming out once every 6 months.
However, unlike Python 3000, Java’s breaking changes were extremely limited. Only JVM internals would be restricted or removed. That’s it. All the existing language features were still available for use. All the JVM bytecode and classes still worked. Want to use a class written in 1995? If it doesn’t depend on sun.* code, it’s good to go!
But, this is also why so many people thought upgrading was impossible. So much Java code out there had taken liberties with the JDK internals. Want to use sun.misc.Unsafe? It’s yours for the taking. Want to modify final (a.k.a. const) fields? It’s only a little reflection away. Want to inject some classes into the JDK classloader? No one will stop you.
With no teeth in the API boundaries, Java 8 pretty much let application and library owners do what they wanted. Guice, Guava, Jackson, Groovy, Gradle, CGLib, Mockito, Lombok, ErrorProne, and other common Java tech played fast and loose with the guts of the JVM. Yes, their code was faster. But no, it wasn’t a long term win.
This is where that tough decision by someone who works on Java comes into play. Java could improve itself, add features, and improve the VM, but it would come at the cost of breaking the ecosystem. Many libraries, which had claimed wins, would have to give them back. Alternatives would be provided, but everyone would have to coordinate a worldwide, backwards compatible, multi-version upgrade. Every library not wanting to yield their gains would need to be rewritten. Most poignantly though, applications would need to wait till every library they depended on to make this move.
Two things stand out to me about this decision:
Having strong, enforceable API boundaries are necessary for long term improvements. Short term wins, while alluring, usually come with non-standard or unsupported baggage. The stricter it is today, the more maintainable it is in the future.
Taking away functionality, even under the auspices of standards or specifications, is going to hurt. If it used to work, and you break it, it’s your fault.
Java 11
When I joined Netflix, no one told me it was impossible to upgrade from Java 8 to 11. I just started using it. When things didn’t work (and they definitely didn’t!) on 11, I went and checked if I needed to update the library. I did this as a back-burner project, on my own machine, separate from the main repo. One by one, all the non-working libraries were updated to the working ones. When a library was not Java 11 compatible, I filed a PR on GitHub to fix it. And, plain as it sounds, when there are no more broken things, only working things are left!
It was only after I pushed these changes to production, that I found out what I did was impossible. Numerous people asked me how I made this happen. Someone, or some group, had looked at the daunting task of updating hundreds of projects and probably hundreds more libraries, and had given up hope. Like a poison placebo, people’s perception of the impossibility actually made it impossible. Socialize these obstacles and you end up with a whole company finding it insurmountable.
When I told them how I fixed it, they were usually disappointed. “Just updated the libraries?” they would ask, looking for something deeper. Java 11 was time-consuming to upgrade to, but not very hard. The only difference between my approach and theirs was a lack of despair.
I bring up this story to boost the confidence in others that using the latest and greatest is within grasp. A month ago I updated our code to Java 15, and last week to 16. It gets easier each time. Once you are close to the latest version, it’s no challenge to stay there. Since the only breaking changes were hiding JVM internals, and we’re no longer using those, it’s trivial to update. As a reward, we get all the advanced features (better JIT, GC, language features, etc.) that have been delivered over the past years.
I encourage you to take a look at updating too, since it is probably easier than you think!
//我带来这个故事是为了给其他人信心. 切换最新最棒的版本易如反掌. 一个月前我更新代码到java 15, 上个星期到16, 每次变得更加简单了. 一旦你接近了最新的版本, 保持下去就不是难事了. 因为最大的改变在JVM内部, 而且我们已经不需要使用它了, 更新是件小事而已啦. 作为回报, 我们可以升级那些发布了好多年的功能(比如运行时编译, 语言特性, 垃圾回收等等).
//我建议你们也来试下更新, 因为它比你想象的更简单.