nipafx news
Published in

nipafx news

Reflective Access, Maven On Java 9, And Speeding Through The Night

CodeFX Weekly #19 — 19th of May 2017

Hi everyone,

once again this weekly is full of Java 9. I discuss yesterday’s proposal to by default allow reflective access to internal APIs and then look at a hurdle I encountered when building a project with Maven and Java 9. The project of the week helps you unit test your architecture.

I send this newsletter out every Friday. Yes, as an actual email. Subscribe!

Java 9 News

Taking JPMS Into The Wrong Direction

As I’m sure you know by now, the module system brings strong encapsulation to the Java platform, where modules can hide their internals and not even reflection can work around that. If applications, be it their own code or their libraries and frameworks, depend on internal APIs, then they can get access to them by using the --add-exports and --add-opens flag. And for a while, things were good.

Then people started complaining about sun.misc.Unsafe, how everybody used it and how it was not fair to make users of it add such complicated flags. So it was decided that Unsafe (and other critical APIs) will end up in a module jdk.unsupported, so they are still freely accessible. And for a while, things were good.

Then people started complaining that they were using so many other internal types, too, and having to identify all of them was too much work and adding so many command line flags could not be expected from busy developers. So it was decided that there would be a “kill switch”, a flag --permit-illegal-access, which would in one sweep allow all legacy code (i.e. the class path) to access JDK internals. As a trade off it would emit warning messages, informing you of your sin. And for a while, things were good.

Then came the JSR 376 vote and still people bitched that life was too hard and that even adding that one flag and having to live with warnings in the log is too much of a burden on the developer’s feeble mind. How could anybody be expected to do all that hard work of finding the place where to add --permit-illegal-access? And anyway, why does Oracle never listen? You never listen!

So here comes Mark Reinhold’s newest proposal:

I hereby propose to allow illegal reflective access from code on the class path by default in JDK 9, and to disallow it in a future release.

In short, the existing “big kill switch” of the --permit-illegal-access option [1] will become the default behavior of the JDK 9 run-time system, though without as many warnings. The current behavior of JDK 9, in which illegal reflective-access operations from code on the class path are not permitted, will become the default in a future release. Nothing will change at compile time.

I can’t even… Here’s my opinion on the matter:

I think making the lenient option the default is a bad decision, needlessly prolonging a proper clean-up of the ecosystem without any practical benefit!

Java’s stewards have been warning against using internal APIs for 20 years. Jigsaw announced to make them inaccessible for nigh two years now. Java 8 will be supported until at least July 2018 and even after that all that is needed to get around this specific Java 9 compatibility problem is to add --permit-illegal-access.

All that is not enough, though? Even adding that single flag is too hard? If spending an hour or two reading up on JPMS and then adding that flag is too much to ask, then how can one expect the same people to clean up their code?

With illegal access being permitted by default much fewer developers will be aware of the problem and much less pressure will be put on library and framework maintainers as well as on project management to invest into paying back this particular form of technical debt. So we get much less momentum to make the necessary changes in exchange for… not having to add a flag? That’s ridiculous, an Armutszeugnis for the Java community!

It looks like this will turn out to be a minority report, though — almost everybody else loves that their applications, libraries, and frameworks can continue to violate encapsulation without them having to change anything for Java 9.

Things will be different for Java 10, though, believe me. Everybody will have updated their code by then, so no one will complain when the JVM gets more restrictive.

I believe it when I see it.

Java 9 Code

What’s the difference between add-exports and add-opens?

That question was asked on StackOverflow and here’s my answer:

  • With --add-exports the package is exported, meaning all public types and members therein are accessible at compile and run time.
  • With --add-opens the package is opened, meaning all types and members (not only public ones!) therein are accessible at run time.

So the main difference at run time is that --add-opens allows "deep reflection", meaning access of non-public members. You can typically identify this kind of access by the reflecting code making calls to setAccessible(true).

Maven And Java 9 Flags

One way to start migrating a project to Java 9 is to compile it with javac 9. There are different ways to do this with Maven and one of them (.mavenrc file) leads to the entire Maven process running on Java 9. For reasons I'm not going into we need Maven to run on Java 9 anyway so we took that approach.

But: Some Maven plugins operate on internal APIs or depend on Java EE modules (which have to be added manually), so the JVM running them needs to be launched with some command line flags like --add-opens (although maybe not much longer - see above) or --add-modules. No problem if they can be forked into their own process but that is not always implemented. In those cases they run in the Maven process, meaning Maven must be launched with the appropriate flags.

This is possible by creating a file .mvn/jvm.config in the project's folder (see documentation). Unfortunately the project can then no longer be built with Java 8 because Maven applies the flags it finds in that file when launching the JVM but version 8 does of course not know any of them and hence barfs. We have some ideas how to fix that once we want to set up a CI build but during experimentation, where you occasionally want to switch between 8 and 9, that really sucks.

Hunting down a differnet compatibility problem I started to switch constantly, though, and to not go bonkers I created the following script:

Depending which versions I want to run on, it creates the following configuration:

Java 8:

  • the JAVA_HOME line in .mavenrc is commented out, starting the process with "system Java"
  • the project’s .mvn folder contains no file called jvm.config (if it existed it was renamed to jvm9.config)

Java 9:

  • the JAVA_HOME line in .mavenrc is not commented out, starting the process with the defined Java, which is 9
  • the project’s .mvn folder may contain a file called jvm.config (if it existed as jvm9.config)

That saved a lot of time. Only caveat: If you have several projects and switch one to Java 8 (for example), another one might still be partially stuck on Java 9 because the .mvn/jvm.config is not renamed across subprojects.

Bla Bla Bla

I was recently interviewed by the Talking Tech Podcast about Java 9 (in German). It was released last Monday and you should totally check it out! If you like it (or any of other Talking Tech Podcasts), give the guys a shout out. They are still pretty new and can use the publicity.

Then I went to RigaDevDays, where I talked about JUnit 5 on Tuesday (video pending, slides, check out parameterized tests) and gave a one-day Java 9 course on Wednesday.

On Thursday I flew back to Frankfurt, took a car to Braunschweig, told the JUG Ostfalen that Java 9 is coming (slides), drove the car back to Frankfurt, hopped into a train home (Karlsruhe), where I arrived after 23 hours of travel — intense.

It has been some time since I drove long distance (well, “long”… three hours each way) and it was great fun to do it again! Listened to Rachel Maddow (Trump’s special prosecutor), Software Engineering Daily (digital ownership), Rammstein (Mutter), Metallica (Master of Puppets), and — the geek cherry on this nerd sundae — Wil Wheaton and his friends play the pen and paper RPG Titansgrave (I’m not actually too enthused about their style to play but it’s still fun to listen to).

Speeding through the night, 190 km/h, speakers blaring “Master! Master!”… I missed that.

Project Of The Week

This week’s project is ArchUnit, which I will let speak for itself:

ArchUnit is a free, simple and extensible library for checking the architecture of your Java code. That is, ArchUnit can check dependencies between packages and classes, layers and slices, check for cyclic dependencies and more. It does so by analyzing given Java bytecode, importing all classes into a Java code structure. ArchUnit’s main focus is to automatically test architecture and coding rules, using any plain Java unit testing framework.

It looks like this:

Isn’t that something?

Shots

This is the shot to end all shots: What The Fuck Just Happened Today? Every Californian afternoon Matt Kiser summarizes all the weird shit the Trump administration got caught up in in a succinct list, summarizing each event in a handful of lines, linking to primary sources. Priceless. Also: Fear inducing! On Twitter, too.

so long … Nicolai

PS: Don’t forget to subscribe or recommend! :)

--

--

--

Whatever recently caught my interest: a thrilling development in the Java community, libraries or tools I am using, what I’ve written or read that might interest you, fascinating questions on StackOverflow, odd tweets, etc. I also send this out via email: https://nipafx.dev/news/

Recommended from Medium

Paralympian @madison.____

Draw a Line to AR World- App Dev Series 18

Reasons to use Gauge automation framework

Ad-hoc Tools for Sharing Jupyter Notebooks in AWS SageMaker

Weeknotes 05x06: Putting the “Go” into Godzilla

bad mentor

Kali Docker on Windows — The Discussion — Setup (Shortish guide)

Data Replication from PostgreSQL to Snowflake with Python

everyday data engineering — data replication from postgresql to snowflake with python

Testing Arrays and Objects with Chai.js

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store

Nicolai Parlog

Nicolai is a #Java enthusiast with a passion for learning and sharing — in posts & books; in videos & streams; at conferences & in courses. https://nipafx.dev

More from Medium

Temporal or restricted ideas — Java

Suggested Learning Path for Java

Inheritance and Polymorphism

A sneak peek into Java8 Stream Transformation and Terminal Operations