diff --git a/util/io/src/main/scala/sbt/IO.scala b/util/io/src/main/scala/sbt/IO.scala index 45b0b2018..92587bb30 100644 --- a/util/io/src/main/scala/sbt/IO.scala +++ b/util/io/src/main/scala/sbt/IO.scala @@ -77,13 +77,22 @@ object IO { * If the location cannot be determined or if it is not a file, an error is generated. * Note that Java standard library classes typically do not have a location associated with them. */ - def classLocationFile(cl: Class[_]): File = { - val classURL = - Option(cl.getProtectionDomain.getCodeSource).getOrElse { - sys.error("No class location for " + cl) - }.getLocation - toFile(classURL) - } + def classLocationFile(cl: Class[_]): File = + Option(cl.getProtectionDomain.getCodeSource) match { + case Some(codeSource) => + val classURL = codeSource.getLocation + toFile(classURL) + case None => + // NB: This assumes that classes without code sources are System classes, and thus located in + // jars. It assumes that `urlAsFile` will truncate to the containing jar file. + val clsfile = s"${cl.getName.replace('.', '/')}.class" + Option(ClassLoader.getSystemClassLoader.getResource(clsfile)) + .flatMap { + urlAsFile + }.getOrElse { + sys.error("No class location for " + cl) + } + } /** * Returns a URL for the classfile containing the given class file for type `T` (as determined by an implicit Manifest). @@ -104,7 +113,7 @@ object IO { sys.error("No class location for " + cl) } } catch { - case e => + case e: Throwable => e.printStackTrace() throw e }