@@ -36,17 +36,25 @@ object PathResolver {
36
36
/** Values found solely by inspecting environment or property variables.
37
37
*/
38
38
object Environment {
39
- private def searchForBootClasspath = (
40
- systemProperties find (_._1 endsWith " .boot.class.path" ) map (_._2) getOrElse " "
41
- )
39
+ private def searchForBootClasspath = {
40
+ import scala .jdk .CollectionConverters .*
41
+ val props = System .getProperties
42
+ // This formulation should be immune to ConcurrentModificationExceptions when system properties
43
+ // we're unlucky enough to witness a partially published result of System.setProperty or direct
44
+ // mutation of the System property map. stringPropertyNames internally uses the Enumeration interface,
45
+ // rather than Iterator, and this disables the fail-fast ConcurrentModificationException.
46
+ val propNames = props.stringPropertyNames()
47
+ propNames.asScala collectFirst { case k if k endsWith " .boot.class.path" => props.getProperty(k) } getOrElse " "
48
+ }
42
49
43
50
/** Environment variables which java pays attention to so it
44
51
* seems we do as well.
45
52
*/
46
53
def classPathEnv : String = envOrElse(" CLASSPATH" , " " )
47
54
def sourcePathEnv : String = envOrElse(" SOURCEPATH" , " " )
48
55
49
- def javaBootClassPath : String = propOrElse(" sun.boot.class.path" , searchForBootClasspath)
56
+ // using propOrNone/getOrElse instead of propOrElse so that searchForBootClasspath is lazy evaluated
57
+ def javaBootClassPath : String = propOrNone(" sun.boot.class.path" ) getOrElse searchForBootClasspath
50
58
51
59
def javaExtDirs : String = propOrEmpty(" java.ext.dirs" )
52
60
def scalaHome : String = propOrEmpty(" scala.home" )
0 commit comments