From f23107fc43168e53032f8bec933d3afdc58bab5e Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 30 Jul 2025 13:34:30 +0100 Subject: [PATCH] Remove java8 home and scala steward pins related to java 11 and java 17 (#1968) * remove use of java8 home * scala deprecations * upgrade paradox * getId is deprecated * remove targetSystemJdk build option * Update JdkOptions.scala --- .scala-steward.conf | 11 --- .../actor/typed/internal/LoggerClass.scala | 2 + .../org/apache/pekko/util/StackBench.scala | 2 + project/Doc.scala | 9 +- project/Jdk9.scala | 21 ++--- project/JdkOptions.scala | 88 +++---------------- project/PekkoBuild.scala | 33 ++----- project/TestExtras.scala | 4 +- project/plugins.sbt | 2 + .../tcp/ssl/PemManagersProviderSpec.scala | 4 +- .../remote/classic/RemoteInitErrorSpec.scala | 2 + 11 files changed, 40 insertions(+), 138 deletions(-) diff --git a/.scala-steward.conf b/.scala-steward.conf index abe0d218ad..7e3010e7a2 100644 --- a/.scala-steward.conf +++ b/.scala-steward.conf @@ -1,17 +1,6 @@ updates.pin = [ - # Pin logback to v1.3.x because v1.4.x needs JDK11 - { groupId = "ch.qos.logback", version="1.3." } - # Pin sbt-paradox to v0.9.x because 0.10.x needs JDK 11 - { groupId = "com.lightbend.paradox", artifactId = "sbt-paradox-project-info", version = "0.9." } - { groupId = "com.lightbend.paradox", artifactId = "sbt-paradox", version = "0.9." } # Scala 3.3 is the latest LTS version { groupId = "org.scala-lang", artifactId = "scala3-library", version = "3.3." } - # aeron 1.46 requires Java 17 - { groupId = "io.aeron", version = "1.45." } - # agrona 1.23 requires Java 17 - { groupId = "org.agrona", artifactId = "agrona", version = "1.22." } - # bndlib 7 requires Java 17 - { groupId = "biz.aQute.bnd", artifactId = "biz.aQute.bndlib", version = "6." } ] updates.ignore = [ diff --git a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/LoggerClass.scala b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/LoggerClass.scala index b73d46b43f..a62e0b350a 100644 --- a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/LoggerClass.scala +++ b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/LoggerClass.scala @@ -13,6 +13,7 @@ package org.apache.pekko.actor.typed.internal +import scala.annotation.nowarn import scala.util.control.NonFatal import org.apache.pekko @@ -26,6 +27,7 @@ import pekko.util.OptionVal private[pekko] object LoggerClass { // just to get access to the class context + @nowarn("msg=deprecated") private final class TrickySecurityManager extends SecurityManager { def getClassStack: Array[Class[_]] = getClassContext } diff --git a/bench-jmh/src/main/scala/org/apache/pekko/util/StackBench.scala b/bench-jmh/src/main/scala/org/apache/pekko/util/StackBench.scala index 3120124ac5..d427426785 100644 --- a/bench-jmh/src/main/scala/org/apache/pekko/util/StackBench.scala +++ b/bench-jmh/src/main/scala/org/apache/pekko/util/StackBench.scala @@ -14,6 +14,7 @@ package org.apache.pekko.util import java.util.concurrent.TimeUnit +import scala.annotation.nowarn import org.openjdk.jmh.annotations.{ Benchmark, Measurement, Scope, State } @@ -21,6 +22,7 @@ import org.openjdk.jmh.annotations.{ Benchmark, Measurement, Scope, State } @Measurement(timeUnit = TimeUnit.MICROSECONDS) class StackBench { + @nowarn("msg=deprecated") class CustomSecurtyManager extends SecurityManager { def getTrace: Array[Class[_]] = getClassContext diff --git a/project/Doc.scala b/project/Doc.scala index a2528d2d66..11f34b16ea 100644 --- a/project/Doc.scala +++ b/project/Doc.scala @@ -140,10 +140,9 @@ object UnidocRoot extends AutoPlugin { lazy val pekkoSettings = UnidocRoot.CliOptions.genjavadocEnabled .ifTrue(Seq( - JavaUnidoc / unidoc / javacOptions := { - if (JdkOptions.isJdk8) Seq("-Xdoclint:none") - else Seq("-Xdoclint:none", "--ignore-source-errors", "--no-module-directories") - })) + JavaUnidoc / unidoc / javacOptions := + Seq("-Xdoclint:none", "--ignore-source-errors", "--no-module-directories") + )) .getOrElse(Nil) override lazy val projectSettings = { @@ -214,8 +213,6 @@ object BootstrapGenjavadoc extends AutoPlugin { override lazy val requires = UnidocRoot.CliOptions.genjavadocEnabled .ifTrue { - // require 11, fail fast for 8, 9, 10 - require(JdkOptions.isJdk11orHigher, "Javadoc generation requires at least jdk 11") sbtunidoc.GenJavadocPlugin } .getOrElse(plugins.JvmPlugin) diff --git a/project/Jdk9.scala b/project/Jdk9.scala index 422b6d65e6..ac4d1871bb 100644 --- a/project/Jdk9.scala +++ b/project/Jdk9.scala @@ -15,14 +15,11 @@ import sbt.Keys._ import sbt._ object Jdk9 extends AutoPlugin { - import JdkOptions.notOnJdk8 import JdkOptions.JavaVersion._ - // The version 9 is special for any Java versions >= 9 - // and the version 11 is special for any Java versions >= 11 - // and the version 17 is special for any Java versions >= 17 + // The version 17 is special for any Java versions >= 17 // and the version 21 is special for any Java versions >= 21 - private val supportedJavaLTSVersions = List("9", "11", "17", "21") + private val supportedJavaLTSVersions = List("17", "21") lazy val CompileJdk9 = config("CompileJdk9").extend(Compile) @@ -59,15 +56,15 @@ object Jdk9 extends AutoPlugin { lazy val compileJdk9Settings = Seq( // following the scala-2.12, scala-sbt-1.0, ... convention - unmanagedSourceDirectories := notOnJdk8(additionalSourceDirectories.value), - scalacOptions := PekkoBuild.DefaultScalacOptions.value ++ notOnJdk8(Seq("-release", majorVersion.toString)), - javacOptions := PekkoBuild.DefaultJavacOptions ++ notOnJdk8(Seq("--release", majorVersion.toString))) + unmanagedSourceDirectories := additionalSourceDirectories.value, + scalacOptions := PekkoBuild.DefaultScalacOptions.value ++ Seq("-release", majorVersion.toString), + javacOptions := PekkoBuild.DefaultJavacOptions ++ Seq("--release", majorVersion.toString)) lazy val testJdk9Settings = Seq( // following the scala-2.12, scala-sbt-1.0, ... convention - unmanagedSourceDirectories := notOnJdk8(additionalTestSourceDirectories.value), - scalacOptions := PekkoBuild.DefaultScalacOptions.value ++ notOnJdk8(Seq("-release", majorVersion.toString)), - javacOptions := PekkoBuild.DefaultJavacOptions ++ notOnJdk8(Seq("--release", majorVersion.toString)), + unmanagedSourceDirectories := additionalTestSourceDirectories.value, + scalacOptions := PekkoBuild.DefaultScalacOptions.value ++ Seq("-release", majorVersion.toString), + javacOptions := PekkoBuild.DefaultJavacOptions ++ Seq("--release", majorVersion.toString), compile := compile.dependsOn(CompileJdk9 / compile).value, classpathConfiguration := TestJdk9, externalDependencyClasspath := (Test / externalDependencyClasspath).value) @@ -80,7 +77,7 @@ object Jdk9 extends AutoPlugin { // Since sbt-osgi upgrade to 0.9.5, the fullClasspath is no longer used on packaging when use sbt-osgi, so we have to // add jdk9 products to dependencyClasspathAsJars instead. // Compile / fullClasspath ++= (CompileJdk9 / exportedProducts).value) - Compile / dependencyClasspathAsJars ++= notOnJdk8((CompileJdk9 / exportedProducts).value)) + Compile / dependencyClasspathAsJars ++= (CompileJdk9 / exportedProducts).value) lazy val testSettings = Seq((Test / test) := { (Test / test).value diff --git a/project/JdkOptions.scala b/project/JdkOptions.scala index 269ef1a77e..10bc38c945 100644 --- a/project/JdkOptions.scala +++ b/project/JdkOptions.scala @@ -18,90 +18,24 @@ import sbt.librarymanagement.SemanticSelector import sbt.librarymanagement.VersionNumber object JdkOptions extends AutoPlugin { - object autoImport { - lazy val jdk8home = settingKey[String]("JDK 8 home. Only needs to be set when it cannot be auto-detected by sbt") - lazy val targetSystemJdk = settingKey[Boolean]( - "Target the system JDK instead of building against JDK 8. When this is enabled resulting artifacts may not work on JDK 8!") - } - import autoImport._ lazy val specificationVersion: String = sys.props("java.specification.version") object JavaVersion { - val majorVersion: Int = { - // FIXME replace with Runtime.version() when we no longer support Java 8 - // See Oracle section 1.5.3 at: - // https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html - val version = specificationVersion.split('.') - val majorString = - if (version(0) == "1") version(1) // Java 8 will be 1.8 - else version(0) // later will be 9, 10, 11 etc - majorString.toInt - } + val majorVersion: Int = java.lang.Runtime.version().feature() } - lazy val isJdk8: Boolean = - VersionNumber(specificationVersion).matchesSemVer(SemanticSelector(s"=1.8")) - lazy val isJdk11orHigher: Boolean = - VersionNumber(specificationVersion).matchesSemVer(SemanticSelector(">=11")) - lazy val isJdk17orHigher: Boolean = - VersionNumber(specificationVersion).matchesSemVer(SemanticSelector(">=17")) - lazy val versionSpecificJavaOptions = - if (isJdk17orHigher) { - // for virtual threads - "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" :: - "--add-opens=java.base/java.lang=ALL-UNNAMED" :: - // for aeron - "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED" :: - // for LevelDB - "--add-opens=java.base/java.nio=ALL-UNNAMED" :: Nil - } else Nil + // for virtual threads + "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" :: + "--add-opens=java.base/java.lang=ALL-UNNAMED" :: + // for aeron + "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED" :: + // for LevelDB + "--add-opens=java.base/java.nio=ALL-UNNAMED" :: Nil - def notOnJdk8[T](values: Seq[T]): Seq[T] = if (isJdk8) Seq.empty[T] else values + def targetJdkScalacOptions(scalaVersion: String): Seq[String] = + Seq(if (scalaVersion.startsWith("3.")) "-Xtarget:17" else "release:17") - def targetJdkScalacOptions( - targetSystemJdk: Boolean, - jdk8home: Option[File], - fullJavaHomes: Map[String, File], - scalaVersion: String): Seq[String] = - selectOptions( - targetSystemJdk, - jdk8home, - fullJavaHomes, - Seq(if (scalaVersion.startsWith("3.")) "-Xtarget:8" else "release:8"), - (java8home: File) => Seq("-release", "8")) - def targetJdkJavacOptions( - targetSystemJdk: Boolean, - jdk8home: Option[File], - fullJavaHomes: Map[String, File]): Seq[String] = - selectOptions( - targetSystemJdk, - jdk8home, - fullJavaHomes, - Nil, - // '-release 8' would be a neater option here, but is currently not an - // option because it doesn't provide access to `sun.misc.Unsafe` https://github.com/akka/akka/issues/27079 - (java8home: File) => Seq("-source", "8", "-target", "8", "-bootclasspath", java8home + "/jre/lib/rt.jar")) - - private def selectOptions( - targetSystemJdk: Boolean, - jdk8home: Option[File], - fullJavaHomes: Map[String, File], - jdk8options: Seq[String], - jdk11options: File => Seq[String]): Seq[String] = - if (targetSystemJdk) - Nil - else if (isJdk8) - jdk8options - else - jdk8home.orElse(fullJavaHomes.get("8")) match { - case Some(java8home) => - jdk11options(java8home) - case None => - throw new MessageOnlyException( - "A JDK 8 installation was not found, but is required to build Apache Pekko. To manually specify a JDK 8 installation, set the JAVA_8_HOME environment variable to its path or use the \"set every jdk8home := \\\"/path/to/jdk\\\" sbt command. If you have no JDK 8 installation, target your system JDK with the \"set every targetSystemJdk := true\" sbt command, but beware resulting artifacts will not work on JDK 8") - } - - lazy val targetJdkSettings = Seq(targetSystemJdk := false, jdk8home := sys.env.get("JAVA_8_HOME").getOrElse("")) + val targetJdkJavacOptions = Seq("-source", "17", "-target", "17") } diff --git a/project/PekkoBuild.scala b/project/PekkoBuild.scala index 50d04d0ca5..f5cccef539 100644 --- a/project/PekkoBuild.scala +++ b/project/PekkoBuild.scala @@ -11,7 +11,6 @@ * Copyright (C) 2009-2022 Lightbend Inc. */ -import JdkOptions.autoImport._ import MultiJvmPlugin.autoImport.MultiJvm import com.lightbend.paradox.projectinfo.ParadoxProjectInfoPluginKeys._ @@ -110,14 +109,7 @@ object PekkoBuild { } } - private def jvmGCLogOptions(isJdk11OrHigher: Boolean, isJdk8: Boolean): Seq[String] = { - if (isJdk11OrHigher) - // -Xlog:gc* is equivalent to -XX:+PrintGCDetails. See: - // https://docs.oracle.com/en/java/javase/11/tools/java.html#GUID-BE93ABDC-999C-4CB5-A88B-1994AAAC74D5 - Seq("-Xlog:gc*") - else if (isJdk8) Seq("-XX:+PrintGCTimeStamps", "-XX:+PrintGCDetails") - else Nil - } + private val jvmGCLogOptions: Seq[String] = Seq("-Xlog:gc*") // -XDignore.symbol.file suppresses sun.misc.Unsafe warnings final val DefaultJavacOptions = Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-XDignore.symbol.file") @@ -129,21 +121,12 @@ object PekkoBuild { TestExtras.Filter.settings, // compile options Compile / scalacOptions ++= DefaultScalacOptions.value, - Compile / scalacOptions ++= - JdkOptions.targetJdkScalacOptions( - targetSystemJdk.value, - optionalDir(jdk8home.value), - fullJavaHomes.value, - scalaVersion.value), + Compile / scalacOptions ++= JdkOptions.targetJdkScalacOptions(scalaVersion.value), Compile / scalacOptions ++= (if (allWarnings) Seq("-deprecation") else Nil), Test / scalacOptions := (Test / scalacOptions).value.filterNot(opt => opt == "-Xlog-reflective-calls" || opt.contains("genjavadoc")), - Compile / javacOptions ++= { - DefaultJavacOptions ++ - JdkOptions.targetJdkJavacOptions(targetSystemJdk.value, optionalDir(jdk8home.value), fullJavaHomes.value) - }, - Test / javacOptions ++= DefaultJavacOptions ++ - JdkOptions.targetJdkJavacOptions(targetSystemJdk.value, optionalDir(jdk8home.value), fullJavaHomes.value), + Compile / javacOptions ++= JdkOptions.targetJdkJavacOptions, + Test / javacOptions ++= DefaultJavacOptions ++ JdkOptions.targetJdkJavacOptions, Compile / javacOptions ++= (if (allWarnings) Seq("-Xlint:deprecation") else Nil), doc / javacOptions := Seq(), crossVersion := CrossVersion.binary, @@ -219,7 +202,7 @@ object PekkoBuild { "-Djava.security.egd=file:/dev/./urandom") defaults ++ CliOptions.runningOnCi - .ifTrue(jvmGCLogOptions(JdkOptions.isJdk11orHigher, JdkOptions.isJdk8)) + .ifTrue(jvmGCLogOptions) .getOrElse(Nil) ++ JdkOptions.versionSpecificJavaOptions }, @@ -258,7 +241,6 @@ object PekkoBuild { Test / testOptions += Tests.Argument("-oDF"), mavenLocalResolverSettings, docLintingSettings, - JdkOptions.targetJdkSettings, // a workaround for https://github.com/akka/akka/issues/27661 // see also project/Protobuf.scala that introduces /../ to make "intellij happy" MultiJvm / assembly / fullClasspath := { @@ -319,10 +301,7 @@ object PekkoBuild { lazy val docLintingSettings = Seq( compile / javacOptions ++= Seq("-Xdoclint:none"), test / javacOptions ++= Seq("-Xdoclint:none"), - doc / javacOptions ++= { - if (JdkOptions.isJdk8) Seq("-Xdoclint:none") - else Seq("-Xdoclint:none", "--ignore-source-errors") - }) + doc / javacOptions ++= Seq("-Xdoclint:none", "--ignore-source-errors")) def loadSystemProperties(fileName: String): Unit = { import scala.collection.JavaConverters._ diff --git a/project/TestExtras.scala b/project/TestExtras.scala index b39270e24c..106724994a 100644 --- a/project/TestExtras.scala +++ b/project/TestExtras.scala @@ -15,7 +15,6 @@ import sbt.Keys._ import sbt._ object TestExtras { - import JdkOptions.isJdk8 object Filter { object Keys { lazy val excludeTestNames = settingKey[Set[String]]( @@ -69,8 +68,7 @@ object TestExtras { "The jdk9-only JavaFlowSupportCompileTest.java" -> "stream-tests/target/test-reports/TEST-org.apache.pekko.stream.javadsl.JavaFlowSupportCompileTest.xml") val testsToCheck = - if (isJdk8) baseList - else baseList ::: jdk9Only + baseList ::: jdk9Only testsToCheck.foreach((shouldExist _).tupled) }) diff --git a/project/plugins.sbt b/project/plugins.sbt index 4d0e602066..2bf3cf445f 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -33,5 +33,7 @@ addSbtPlugin("io.github.roiocam" % "sbt-depend-walker" % "0.1.1") addSbtPlugin("com.github.sbt" % "sbt-sbom" % "0.4.0") addSbtPlugin("org.apache.pekko" % "pekko-sbt-paradox" % "1.0.1") +addSbtPlugin("com.lightbend.paradox" % "sbt-paradox-theme" % "0.10.7") +addSbtPlugin("com.lightbend.paradox" % "sbt-paradox" % "0.10.7") addSbtPlugin("com.gradle" % "sbt-develocity" % "1.3") diff --git a/remote/src/test/scala/org/apache/pekko/remote/artery/tcp/ssl/PemManagersProviderSpec.scala b/remote/src/test/scala/org/apache/pekko/remote/artery/tcp/ssl/PemManagersProviderSpec.scala index 4bf2475f91..2049515614 100644 --- a/remote/src/test/scala/org/apache/pekko/remote/artery/tcp/ssl/PemManagersProviderSpec.scala +++ b/remote/src/test/scala/org/apache/pekko/remote/artery/tcp/ssl/PemManagersProviderSpec.scala @@ -16,12 +16,12 @@ package org.apache.pekko.remote.artery.tcp.ssl import java.security.PrivateKey import java.security.cert.Certificate import java.security.cert.X509Certificate +import scala.annotation.nowarn import org.scalatest.matchers.must.Matchers import org.scalatest.wordspec.AnyWordSpec -/** - */ +@nowarn("msg=deprecated") class PemManagersProviderSpec extends AnyWordSpec with Matchers { "A PemManagersProvider" must { diff --git a/remote/src/test/scala/org/apache/pekko/remote/classic/RemoteInitErrorSpec.scala b/remote/src/test/scala/org/apache/pekko/remote/classic/RemoteInitErrorSpec.scala index 09bb9e7cdf..25c13db072 100644 --- a/remote/src/test/scala/org/apache/pekko/remote/classic/RemoteInitErrorSpec.scala +++ b/remote/src/test/scala/org/apache/pekko/remote/classic/RemoteInitErrorSpec.scala @@ -13,6 +13,7 @@ package org.apache.pekko.remote.classic +import scala.annotation.nowarn import scala.collection.mutable.Set import scala.concurrent.duration._ import scala.util.control.NonFatal @@ -48,6 +49,7 @@ class RemoteInitErrorSpec extends AnyWordSpec with Matchers { } """).resolve() + @nowarn("msg=deprecated") def currentThreadIds(): Set[Long] = { val threads = Thread.getAllStackTraces().keySet() threads.asScala.collect { case t: Thread if !t.isDaemon() => t.getId() }