diff options
author | Nikolay Tatarinov <5min4eq.unity@gmail.com> | 2018-03-25 11:36:01 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-25 11:36:01 +0300 |
commit | f45f11b88fe00ea6fecb44e7da0aadbfffd01b25 (patch) | |
tree | f2cc04c4ac4244fc336aea1ed1fd523cfac30513 | |
parent | f8cea556bf2d0989c371d104f3c862c666ebdfce (diff) | |
download | mill-f45f11b88fe00ea6fecb44e7da0aadbfffd01b25.tar.gz mill-f45f11b88fe00ea6fecb44e7da0aadbfffd01b25.tar.bz2 mill-f45f11b88fe00ea6fecb44e7da0aadbfffd01b25.zip |
try to fix classloading issues on runLocal and test with java 9 (#255)
* fix class loading for inprocess in java 9
* always add rt jar in case of java 9
* move all custom classloading logic into mill.util.ClassLoader
* add comments explaining parent class loader changes and comment in tests pointing to original issue
-rwxr-xr-x | build.sc | 3 | ||||
-rw-r--r-- | core/src/mill/util/ClassLoader.scala | 68 | ||||
-rw-r--r-- | main/src/mill/modules/Jvm.scala | 17 | ||||
-rw-r--r-- | scalalib/test/resources/hello-world/core/src/Main.scala | 9 |
4 files changed, 71 insertions, 26 deletions
@@ -25,6 +25,9 @@ trait MillPublishModule extends PublishModule{ Developer("lihaoyi", "Li Haoyi","https://github.com/lihaoyi") ) ) + + def javacOptions = Seq("-source", "1.8", "-target", "1.8") + } object moduledefs extends MillPublishModule{ def ivyDeps = Agg( diff --git a/core/src/mill/util/ClassLoader.scala b/core/src/mill/util/ClassLoader.scala index b53150c2..d650aceb 100644 --- a/core/src/mill/util/ClassLoader.scala +++ b/core/src/mill/util/ClassLoader.scala @@ -2,25 +2,63 @@ package mill.util import java.net.{URL, URLClassLoader} +import ammonite.ops._ import io.github.retronym.java9rtexport.Export object ClassLoader { + + def create(urls: Seq[URL], parent: java.lang.ClassLoader)( + implicit ctx: Ctx.Home): URLClassLoader = { + new URLClassLoader( + makeUrls(urls).toArray, + refinePlatformParent(parent) + ) + } + def create(urls: Seq[URL], - parent: java.lang.ClassLoader) - (implicit ctx: Ctx.Home): URLClassLoader = { - val cl = new URLClassLoader(urls.toArray, parent) - if (!ammonite.util.Util.java9OrAbove) return cl - try { - cl.loadClass("javax.script.ScriptEngineManager") - cl - } catch { - case _: ClassNotFoundException => - val path = ctx.home - val rtFile = new java.io.File(path.toIO, s"rt-${System.getProperty("java.version")}.jar") - if (!rtFile.exists) { - java.nio.file.Files.copy(Export.export().toPath, rtFile.toPath) - } - new URLClassLoader((urls ++ Some(rtFile.toURI.toURL)).toArray, parent) + parent: java.lang.ClassLoader, + customFindClass: String => Option[Class[_]])( + implicit ctx: Ctx.Home): URLClassLoader = { + new URLClassLoader( + makeUrls(urls).toArray, + refinePlatformParent(parent) + ) { + override def findClass(name: String): Class[_] = { + customFindClass(name).getOrElse(super.findClass(name)) + } + } + } + + /** + * Return `ClassLoader.getPlatformClassLoader` for java 9 and above, if parent class loader is null, + * otherwise return same parent class loader. + * More details: https://docs.oracle.com/javase/9/migrate/toc.htm#JSMIG-GUID-A868D0B9-026F-4D46-B979-901834343F9E + * + * `ClassLoader.getPlatformClassLoader` call is implemented via runtime reflection, cause otherwise + * mill could be compiled only with jdk 9 or above. We don't want to introduce this restriction now. + */ + private def refinePlatformParent(parent: java.lang.ClassLoader): ClassLoader = { + if (ammonite.util.Util.java9OrAbove) { + if (parent == null) + classOf[ClassLoader] + .getMethod("getPlatformClassLoader") + .invoke(null) + .asInstanceOf[ClassLoader] + else parent + } else { + parent + } + } + + private def makeUrls(urls: Seq[URL])(implicit ctx: Ctx.Home): Seq[URL] = { + if (ammonite.util.Util.java9OrAbove) { + val rtFile = ctx.home / s"rt-${System.getProperty("java.version")}.jar" + if (!exists(rtFile)) { + cp(Path(Export.export()), rtFile) + } + urls :+ rtFile.toNIO.toUri.toURL + } else { + urls } } } diff --git a/main/src/mill/modules/Jvm.scala b/main/src/mill/modules/Jvm.scala index 9c63d108..92469988 100644 --- a/main/src/mill/modules/Jvm.scala +++ b/main/src/mill/modules/Jvm.scala @@ -103,19 +103,16 @@ object Jvm { classLoaderOverrideSbtTesting: Boolean, body: ClassLoader => T) (implicit ctx: Ctx.Home): T = { + val urls = classPath.map(_.toIO.toURI.toURL) val cl = if (classLoaderOverrideSbtTesting) { val outerClassLoader = getClass.getClassLoader - new URLClassLoader(classPath.map(_.toIO.toURI.toURL).toArray, mill.util.ClassLoader.create(Seq(), null)){ - override def findClass(name: String) = { - if (name.startsWith("sbt.testing.")){ - outerClassLoader.loadClass(name) - }else{ - super.findClass(name) - } - } - } + mill.util.ClassLoader.create(urls.toVector, null, customFindClass = { name => + if (name.startsWith("sbt.testing.")) + Some(outerClassLoader.loadClass(name)) + else None + }) } else { - mill.util.ClassLoader.create(classPath.map(_.toIO.toURI.toURL).toVector, null) + mill.util.ClassLoader.create(urls.toVector, null) } val oldCl = Thread.currentThread().getContextClassLoader Thread.currentThread().setContextClassLoader(cl) diff --git a/scalalib/test/resources/hello-world/core/src/Main.scala b/scalalib/test/resources/hello-world/core/src/Main.scala index 32706d44..d86f4da8 100644 --- a/scalalib/test/resources/hello-world/core/src/Main.scala +++ b/scalalib/test/resources/hello-world/core/src/Main.scala @@ -1,5 +1,8 @@ import scala.collection._ import java.nio.file.{Files, Paths} +import java.sql.Date +import java.time.LocalDate +import javax.swing.JButton import Main.{args, greeting} object Main0{ @@ -10,7 +13,11 @@ object Main0{ } } object Main extends App { - + // testing correct loading of java standard modules in java 9 + // https://github.com/lihaoyi/mill/issues/251 + new JButton("hello from javax") + val now = Date.valueOf(LocalDate.now()) + println(s"Today is the date: ${now}") val person = Person.fromString("rockjam:25") val greeting = s"hello ${person.name}, your age is: ${person.age}" println(greeting) |