Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use release 8 scalac flag to allow building on JDK11+ #187

Merged
merged 1 commit into from Jun 18, 2023

Conversation

mdedetrich
Copy link
Contributor

@mdedetrich mdedetrich commented Jun 18, 2023

This PR is the equivalent of apache/pekko#258 but for pekko-http. The context behind these changes are complicated (read the linked pekko PR for more detail) but long story short the release scalac flag for Scala 2 changed at some point. The original version of release flag (which the code currently in pekko-http was written for) only makes scalac produce JDK 8 bytecode but it ignores the JDK 8 runtime rt.jar. This is almost never what you want, so the same flag was updated in later versions of Scala (see scala/scala#9982) which also brings in the correct rt.jar, i.e. if you build a project using JDK 11 with the -release:8 flag then not only will it produce JDK8 bytecode but it will also bring in JDK 8's rt.jar.

That part about bringing in the rt.jar 8 jar is critical because, because there was a change from JDK 8 to JDK9's stdlib where if you compile a codebase with JDK9+, because of a newly added overloaded method that is only available in JDK9+ the produced bytecode will reference that new method rather than the JDK8 one. This is what was documented in https://github.com/apache/incubator-pekko/pull/258/files#diff-c11a10bd9e773399e4272cd1ee5dff72545afb2f8bed23f2d1bbc49d4e1fc03fL61-L66.

tl;dr Since we are using the most modern versions of scalac, we can just use release:8 and it handles the corner cases described above. pekko-core had code in sbt to prevent building without an available JDK 8, pekko-http had the same core issue with the deprecated flag but it seems that this same check wasn't added.

To verify that this PR does in fact produce the same bytecode as if the project was compiled under JDK 8 https://github.com/lightbend-labs/jardiff was used. Its fairly easy to verify this yourself, clone incubator-pekko into a new directory (lets call it incubator-pekko-2) and compile it under JDK 8 using sbt ++compile. Then compile this branch/PR in an incubator-pekko folder using JDK 11 and create a new folder called diff-temp. Then you can just run

jardiff -g ~/github/diff-temp/ ~/github/incubator-pekko-http/http-core/target/scala-2.12/ ~/github/incubator-pekko-http-2/http-core/target/scala-2.12/

Which creates a git repository in diff-temp showing the bytecode diff. Using a git diff viewer (I use Intellij) you get the following

image

As you can see while there are some difference its not anything of consequence (i.e. Version has changed but thats because the project version which is derived from the git has changed).

If we however run the jardiff tool without the changes in this PR/branch we get the following

image

Notice how we now have differences in HttpHeaderParser/CustomCharsetByteStringRenderer, and if we view what the difference is we get

image

Which is precisely the problem talked about earlier.

Copy link
Contributor

@pjfanning pjfanning left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mdedetrich mdedetrich merged commit 6ab07a9 into apache:main Jun 18, 2023
13 checks passed
@mdedetrich mdedetrich deleted the use-release-8-flag branch June 18, 2023 21:04
@jrudolph
Copy link
Contributor

This change shouldn't have any effect.

-release 8 was added before for any other JDK than JDK 8. Now it is also added for JDK 8 where it never was necessary (but was forbidden for older versions of scalac).

@mdedetrich
Copy link
Contributor Author

mdedetrich commented Jun 26, 2023

This change shouldn't have any effect.

Those changes definitely have an effect if you build with JDK 11, they allow you to build with JDK 11 and produce completely compatible JKD 8 bytecode.

With JDK 8 there is no effect, it's detailed in the PR.

"-Wconf:msg=reached max recursion depth:s") ++
(if (isJdk8) Seq.empty
else if (scalaBinaryVersion.value == "2.12") Seq("-target:jvm-1.8")
else Seq("-release", "8")),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here -release 8 was added before. Are you saying that it makes a difference whether -release:8 or -release 8 is used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes the flag was actually updated and improved, the previously linked PR provides all of the details.

@jrudolph
Copy link
Contributor

I see, it only makes a difference for Scala 2.12 where this PR moves from -target:jvm-1.8 to -release:8 (which wasn't supported in earlier versions of 2.12).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants