diff --git a/core/src/main/scala/org/apache/spark/executor/ExecutorURLClassLoader.scala b/core/src/main/scala/org/apache/spark/executor/ExecutorURLClassLoader.scala index 218ed7b5d2d39..f52fea416445a 100644 --- a/core/src/main/scala/org/apache/spark/executor/ExecutorURLClassLoader.scala +++ b/core/src/main/scala/org/apache/spark/executor/ExecutorURLClassLoader.scala @@ -19,56 +19,51 @@ package org.apache.spark.executor import java.net.{URLClassLoader, URL} -import org.apache.spark.util.ParentClassLoader +/** + * A ClassLoader trait that changes the normal delegation scheme. + * Normally, it's (cache, parent, self). GreedyClassLoader uses + * (cache, self, parent). This lets this CL "hide" or "override" + * class defs that also exist in the parent loader. + */ +private[spark] trait GreedyClassLoader extends ClassLoader { + override def loadClass(name: String, resolve: Boolean): Class[_] = { + this.synchronized { + // Check the cache + var c: Class[_] = findLoadedClass(name) + if (c == null) { + try { + // Try loading it ourselves + c = findClass(name) + } catch { + case ignored: ClassNotFoundException => + } + + if (c == null) { + // Finally, try delegating to the parent + c = getParent.loadClass(name) + } + } + if (resolve) { + resolveClass(c) + } + c + } + } +} /** * The addURL method in URLClassLoader is protected. We subclass it to make this accessible. * We also make changes so user classes can come before the default classes. */ - private[spark] trait MutableURLClassLoader extends ClassLoader { - def addURL(url: URL) + def addURL(url: URL) //XXX: this is sketchy and dangerous. ClassLoader instances aren't designed to be mutable. def getURLs: Array[URL] } private[spark] class ChildExecutorURLClassLoader(urls: Array[URL], parent: ClassLoader) - extends MutableURLClassLoader { - - private object userClassLoader extends URLClassLoader(urls, null){ - override def addURL(url: URL) { - super.addURL(url) - } - override def findClass(name: String): Class[_] = { - super.findClass(name) - } - } - - private val parentClassLoader = new ParentClassLoader(parent) - - override def findClass(name: String): Class[_] = { - try { - userClassLoader.findClass(name) - } catch { - case e: ClassNotFoundException => { - parentClassLoader.loadClass(name) - } - } - } - - def addURL(url: URL) { - userClassLoader.addURL(url) - } - - def getURLs() = { - userClassLoader.getURLs() - } + extends URLClassLoader(urls, parent) with GreedyClassLoader with MutableURLClassLoader { } private[spark] class ExecutorURLClassLoader(urls: Array[URL], parent: ClassLoader) extends URLClassLoader(urls, parent) with MutableURLClassLoader { - - override def addURL(url: URL) { - super.addURL(url) - } } -