Skip to content

Commit

Permalink
oss: update all projects with JDK 11 support and travis builds
Browse files Browse the repository at this point in the history
Problem

We want to be able to build and test using JDK 11, but
Dodo and Scrooge do not use compatible Scala and SBT
versions.

Solution

Update Scala and SBT versions used by dodo and scrooge
from Scala 2.10.6 to 2.10.7 and SBT from 0.13.16 to
0.13.18. Each SBT file will contain GC options that
are compatible with the active JDK version. Some logic
has been updated to fix runtime behavior in JDK 11.

Result

Projects can be compiled and tested by both JDK 8 and JDK 11.

JIRA Issues: CSL-8513

Differential Revision: https://phabricator.twitter.biz/D365075
  • Loading branch information
enbnt authored and jenkins committed Oct 24, 2019
1 parent f35ae59 commit e6970ed
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 14 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ scala:

jdk:
- openjdk8
- openjdk11

notifications:
slack:
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ Note that ``PHAB_ID=#`` and ``RB_ID=#`` correspond to associated messages in com
Unreleased
----------

* util: Add initial support for JDK 11 compatibility. ``PHAB_ID=D365075``


New Features
~~~~~~~~~~~~

Expand Down
23 changes: 23 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ def travisTestJavaOptions: Seq[String] = {
}

def gcJavaOptions: Seq[String] = {
val javaVersion = System.getProperty("java.version")
if (javaVersion.startsWith("1.8")) {
jdk8GcJavaOptions
} else {
jdk11GcJavaOptions
}
}

def jdk8GcJavaOptions: Seq[String] = {
Seq(
"-XX:+UseParNewGC",
"-XX:+UseConcMarkSweepGC",
Expand All @@ -51,6 +60,20 @@ def gcJavaOptions: Seq[String] = {
)
}

def jdk11GcJavaOptions: Seq[String] = {
Seq(
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSParallelRemarkEnabled",
"-XX:+CMSClassUnloadingEnabled",
"-XX:ReservedCodeCacheSize=128m",
"-XX:SurvivorRatio=128",
"-XX:MaxTenuringThreshold=0",
"-Xss8M",
"-Xms512M",
"-Xmx2G"
)
}

val defaultProjectSettings = Seq(
scalaVersion := "2.12.8",
crossScalaVersions := Seq("2.11.12", "2.12.8", "2.13.0")
Expand Down
23 changes: 20 additions & 3 deletions util-app/src/main/scala/com/twitter/app/ClassPath.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.twitter.app

import com.twitter.finagle.util.loadServiceIgnoredPaths
import java.io.{IOException, File}
import java.net.{URISyntaxException, URLClassLoader, URI}
import java.io.{File, IOException}
import java.net.{URI, URISyntaxException, URL, URLClassLoader}
import java.nio.charset.MalformedInputException
import java.nio.file.Paths
import java.util.jar.{JarEntry, JarFile}
import scala.collection.mutable
import scala.collection.mutable.Builder
Expand Down Expand Up @@ -62,12 +63,28 @@ private[app] sealed abstract class ClassPath[CpInfo <: ClassPath.Info] {
buf.result
}

// Note: In JDK 9+ URLClassLoader is no longer the default ClassLoader.
// This method allows us to scan URL's on the class path that can be used
// but does NOT include the ModulePath introduced in JDK9. This method is
// used as a bridge between JDK 8 and JDK 9+.
// The method used here is attributed to https://stackoverflow.com/a/49557901.
// TODO - add suppport for the ModulePath after dropping JDK 8 support.
private[this] def urlsFromClasspath(): Array[URL] = {
val classpath: String = System.getProperty("java.class.path")
classpath.split(File.pathSeparator).map { pathEntry: String =>
Paths.get(pathEntry).toAbsolutePath().toUri().toURL
}
}

// package protected for testing
private[app] def getEntries(loader: ClassLoader): Seq[(URI, ClassLoader)] = {
val parent = Option(loader.getParent)

val ownURIs: Vector[(URI, ClassLoader)] = for {
urlLoader <- Vector(loader).collect { case u: URLClassLoader => u }
urlLoader <- Vector(loader).map {
case urlClassLoader: URLClassLoader => urlClassLoader
case cl => new URLClassLoader(urlsFromClasspath(), cl)
}
urls <- Option(urlLoader.getURLs()).toVector
url <- urls if url != null
} yield (url.toURI -> loader)
Expand Down
24 changes: 13 additions & 11 deletions util-core/src/test/scala/com/twitter/util/FutureTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -961,18 +961,20 @@ class FutureTest extends WordSpec with MockitoSugar with ScalaCheckDrivenPropert
}
}

"doesn't leak the underlying promise after completion" in {
new MonitoredHelper {
val inner1 = new Promise[String]
val inner2 = new Promise[String]
val f: Future[String] = Future.monitored { inner2.ensure(()); inner1 }
val s: String = "." * 1024
val sSize: Long = ObjectSizeCalculator.getObjectSize(s)
inner1.setValue(s)
val inner2Size: Long = ObjectSizeCalculator.getObjectSize(inner2)
assert(inner2Size < sSize)
// we only know this works as expected when running with JDK 8
if (System.getProperty("java.version").startsWith("1.8"))
"doesn't leak the underlying promise after completion" in {
new MonitoredHelper {
val inner1 = new Promise[String]
val inner2 = new Promise[String]
val f: Future[String] = Future.monitored { inner2.ensure(()); inner1 }
val s: String = "." * 1024
val sSize: Long = ObjectSizeCalculator.getObjectSize(s)
inner1.setValue(s)
val inner2Size: Long = ObjectSizeCalculator.getObjectSize(inner2)
assert(inner2Size < sSize)
}
}
}
}
}

Expand Down

0 comments on commit e6970ed

Please sign in to comment.