Executor的createClassLoader方法,先得到currentLoader,如果userClassPathFirst为真,返回ChildFirstURLClassLoader,否则返回 MutableURLClassLoader。
/**
* Create a ClassLoader for use in tasks, adding any JARs specified by the user or any classes
* created by the interpreter to the search path
*/
private def createClassLoader(): MutableURLClassLoader = {
// Bootstrap the list of jars with the user class path.
val now = System.currentTimeMillis()
userClassPath.foreach { url =>
currentJars(url.getPath().split("/").last) = now
}
val currentLoader = Utils.getContextOrSparkClassLoader
// For each of the jars in the jarSet, add them to the class loader.
// We assume each of the files has already been fetched.
val urls = userClassPath.toArray ++ currentJars.keySet.map { uri =>
new File(uri.split("/").last).toURI.toURL
}
if (userClassPathFirst) {
new ChildFirstURLClassLoader(urls, currentLoader)
} else {
new MutableURLClassLoader(urls, currentLoader)
}
}
在ChildFirstURLClassLoader里,有两个参数,urls和currentLoader,对应urls和parent。给父类传递的是urls和null,在loadClass里,首先调用父类的loadClass,抛出ClassNotFoundException异常后,再用parent的loadClass()。由于paret是系统的classLoader,达到了如果找不到再用系统classLoader,即把系统的classLoader放到后面。
/**
* A mutable class loader that gives preference to its own URLs over the parent class loader
* when loading classes and resources.
*/
private[spark] class ChildFirstURLClassLoader(urls: Array[URL], parent: ClassLoader)
extends MutableURLClassLoader(urls, null) {
private val parentClassLoader = new ParentClassLoader(parent)
override def loadClass(name: String, resolve: Boolean): Class[_] = {
try {
super.loadClass(name, resolve)
} catch {
case e: ClassNotFoundException =>
parentClassLoader.loadClass(name, resolve)
}
}
override def getResource(name: String): URL = {
val url = super.findResource(name)
val res = if (url != null) url else parentClassLoader.getResource(name)
res
}
override def getResources(name: String): Enumeration[URL] = {
val childUrls = super.findResources(name).asScala
val parentUrls = parentClassLoader.getResources(name).asScala
(childUrls ++ parentUrls).asJavaEnumeration
}
override def addURL(url: URL) {
super.addURL(url)
}
}
MutabbleURLClassLoader直接扩展java的URLClassLoader,非常简单。
/**
* URL class loader that exposes the `addURL` and `getURLs` methods in URLClassLoader.
*/
private[spark] class MutableURLClassLoader(urls: Array[URL], parent: ClassLoader)
extends URLClassLoader(urls, parent) {
override def addURL(url: URL): Unit = {
super.addURL(url)
}
override def getURLs(): Array[URL] = {
super.getURLs()
}