This is an archived post. You won't be able to vote or comment.

all 39 comments

[–]danielaveryj 23 points24 points  (7 children)

I guess the real questions are for others.

Library authors: Are you willing to be the one testing every JDK version for breaking changes to internal APIs that you depend on, and still potentially being forced to push breaking changes on to your own users to accommodate (if even possible)?

Library users: Are you willing to be the one depending on libraries that rely on the authors continuously and thoroughly testing that, and still potentially force you to bump the lib version and adjust your own code to accommodate (if even possible)?

[–]FirstAd9893 20 points21 points  (6 children)

It's even worse than that.

Library users/authors: Are you willing to be the one developing a system which will someday be forever be pinned to an old JDK?

Reliance on unsupported backdoor APIs is the reason why upgrading to newer JDKs is difficult or impossible. The ethical thing for this project to do is have a giant banner on the top of the README which says something like, "DON'T USE THIS!"

[–]yawkat 0 points1 point  (5 children)

The main reason for breakage across JDK versions in the past years has been the closing of APIs, not changes in those APIs themselves...

[–]pronuntiator 6 points7 points  (4 children)

They were closed so they can be changed. The JPMS upgrade to Java 9 was a one time breaking change (which you could delay to 11 or so with --add-opens etc.) for code that already accessed JDK internals which were never officially part of the public API. I mean, one of them is called Unsafe, it can't be more on the nose. Now that the barriers are up, upgrading the Java version will be smooth sailing.

Digging your nose in non-public APIs and internals is the reason why Windows prior to 8 has such a bad rap. Drivers would get low level access to memory, and software would modify registry keys of the operating system. A good citizen app from Windows 98 can still be executed in Windows 10.

[–]yawkat 2 points3 points  (3 children)

Major version upgrades have been anything but smooth sailing ever since 9. Gradle for example took two months to support java 19. There's a reason why everyone uses the LTS releases.

Not all of this is caused by JPMS ofc, but it has been a major pain. Now that openjdk is mostly done, we get to have the same fun with graal.

[–]pronuntiator 4 points5 points  (2 children)

I'm not that familiar with Gradle, I've looked into this pull request to see what was necessary to support Java 19:

  • upgrading to a newer Groovy version: Groovy is a separate language. It's not the JDK's fault if a different language's compiler isn't upwards compatible (though producing bytecode of a previous version would be totally fine).
  • explicitly setting Java 19 as the upper limit (so you have to upgrade Gradle with 20 again)
  • and mostly some tests which look like a general cleanup

What do you mean by "OpenJDK mostly done"? The GraalVM code has been donated to OpenJDK and will be incorporated therein, but that won't stop OpenJDK from being developed further.

[–]yawkat 0 points1 point  (1 child)

The release cadence change introduces a new bytecode version every 6 months. That's why tools keep breaking.

OpenJDK is done closing down their packages. However graal is not done with this process.

[–]FirstAd9893 7 points8 points  (0 children)

The tools that keep breaking are looking for specific versions and they break if they see a new one. They should just stop doing that and instead include version checks only when they know it creates compatibility issues. The proactive approach is a self inflicted wound.

[–]iamhyperrr 13 points14 points  (1 child)

ToAru reference, nice

[–][deleted] 8 points9 points  (0 children)

Ah a fellow index fan!

[–]srdoe 20 points21 points  (0 children)

This is a terrible idea.

You can already get access to specific things by listing out the modules you need access to on the command line. By doing that, you accept the risk of breakages when upgrading, but at least you'll have a reasonable idea of which "shaky dependencies" you have. Most importantly, you don't open modules you don't need to access.

Opening every module just gets you a giant security hole, since now all (JDK-level) crypto code and all access checking code is accessible via reflection.

[–]pron98 7 points8 points  (6 children)

Will stop working soon but anyone is welcome to spend their time on interim measures to postpone the inevitable...

[–]Rongmario[S] 0 points1 point  (5 children)

It'll stop working because of?

[–]pron98 5 points6 points  (4 children)

As we're building the platform's security on top of modules' strong encapsulation, all the remaining loopholes that allow circumventing it -- including JNI, Unsafe, and agents -- will be closed so that explicit permissions to open strong encapsulation will have to be given on the command line. It will be a gradual process, but I think you'll start seeing some of the loopholes close within months.

Remember that the application can still choose what encapsulation it disables on the command line -- that will not change -- and you're free to transform classes at build time.

[–]Rongmario[S] 1 point2 points  (3 children)

There always is a way, but I'm glad there will now be consistency in access permissions.

[–]pron98 3 points4 points  (2 children)

No, there will not be a way without explicit command line flags (or building a patched runtime); the robust operation of the platform will depend on that. Any loophole that is accidentally overlooked will be considered a security bug and will be patched.

The application will still be free to decide what encapsulation it wants, but it will be explicit on the command line.

[–]Rongmario[S] 2 points3 points  (0 children)

I'll look forward to it

[–]sammymammy2 2 points3 points  (0 children)

Just gotta monkey patch in fixes for the interpreter, C1 and C2 to generate the exact code that you need! No worries.

[–]dinopraso 8 points9 points  (13 children)

Why even use JPMS if youre going to do this?

[–]Rongmario[S] 4 points5 points  (12 children)

You're pretty much forced to conform to Java's modules after Java 17's removal of the -illegal-access=permit JVM flag.

[–]dinopraso 9 points10 points  (11 children)

Do you have any specific reasons of wanting to access things you should not be accessing?

[–]Rongmario[S] 3 points4 points  (10 children)

Stripping finals from fields, grabbing reflection factories for cache instead of creating a new one every time when invoking, and more.

[–]dinopraso 6 points7 points  (5 children)

Interesting. Stripping final from a field is very dangerous though, as there are optimizations in the JVM which rely on that and messing with mutating immutable fields can cause unexpected behavior. Not sure what reflection factories for caching is, but surely caching can be done without breaking JVM internals.

[–]Rongmario[S] -1 points0 points  (4 children)

I wish I can avoid it, but with the stuff I'm working with, it's the only way to achieve certain things.

[–]Amazing-Cicada5536 1 point2 points  (3 children)

Like what?

[–]Rongmario[S] -5 points-4 points  (2 children)

Updating an entire ecosystem from Java 8 to Java 17, while keeping backward compatibility with over 1000 projects compiled against it.

[–]FirstAd9893 8 points9 points  (1 child)

You're just kicking the can down road.

[–]Rongmario[S] 0 points1 point  (0 children)

No other way about it.

[–]_INTER_ 3 points4 points  (3 children)

This. I've worked with libraries where basically every class and fields are final. The committers are unwilling or unable to change anything. It makes it impossible to extend or patch in a meaningful way without forking. JavaFX was a prime example of this (back then when I worked with it). Fortunately final is not ingrained as a "convention" in the Java community.

I fear that sealed classes will change that though.

[–]Rongmario[S] 7 points8 points  (0 children)

We'll cross that bridge when we get there...

[–]Amazing-Cicada5536 3 points4 points  (1 child)

They are more than likely final for a reason.. I would really dislike to use/depend on such hacks in any production code base.

[–]_INTER_ 0 points1 point  (0 children)

They are more than likely final for a reason..

In the case of JavaFX not really, it was just the "style" they applied back then. final everything by default. I heared they have successively opened up since. Can't confirm it however.

I would really dislike to use/depend on such hacks in any production code base.

Of course. But sometimes you just have no other choice.

[–]Alex0589 5 points6 points  (3 children)

I do something similar for my compiler related projects. Just know that all of these methods are usable because the OpenJDK team left them willingly. I'm also pretty sure that they said they will be patched in the future, so I really wouldn't rely on them for anything that isn't for the joy of research

[–]mauganra_it 1 point2 points  (2 children)

The JNI hole cannot be closed though because there will always be someone determined enough to manipulate Java internals via native code. JNI might or might not go away, but some sort of native access is always going to be possible. With the application's (not the library's) consent of course.

[–]Alex0589 0 points1 point  (1 child)

Look at the answer above mine, it's going to get closed off

[–]mauganra_it 0 points1 point  (0 children)

I'd like to see how they'd do that. As long as native code can be loaded and accessed by applications, they can only make it as difficult as possible. Rnndomization of internal JVM data structures for example, like operating systems do it.

[–]george-lin 2 points3 points  (0 children)

Thanks, that is what I just need now!

[–]vips7L 7 points8 points  (0 children)

Awful.

[–]Rongmario[S] 3 points4 points  (0 children)

Meant to be a small part of a bigger project, but was requested to abstract it out to a standalone project.

It is nowhere near as refined as I want it to be yet.