tonglin0325的个人主页

Spark学习笔记——Spark加载jar包的过程

给spark任务添加jar包的方式#

spark中使用的jar分成2种,一种是用户自行添加的jar,另一种是spark环境依赖的jar

1.spark环境依赖的jar#

其添加的方式有有下面几种

1.
 --conf spark.driver.extraClassPath=... or --driver-class-path ...

2. --conf spark.driver.extraLibraryPath=..., or --driver-library-path ...

3. --conf spark.executor.extraClassPath=...

4. --conf spark.executor.extraLibraryPath=...

上面的配置参数指定的jar包最终都是放到了系统类加载器的classpath里,由系统类加载器完成加载。

 

2.用户自行添加的jar#

其添加的方式有有下面几种

1. --jars

2. SparkContext.addJar(...) method

3. SparkContext.addFile(...) method

  1. not to forget, the last parameter of the spark-submit is also a .jar file. 也是通过 SparkContext.addJar(...)

用户自行添加的jar会放到Spark自定义的MutableURLClassLoader或者ChildFirstURLClassLoader的classpath中,由其完成加载。

 

3.spark类加载的顺序#

ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。

当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器 **Bootstrap ClassLoader **试图加载,如果没加载到,则把任务转交给 **Extension ClassLoader **试图加载,如果也没加载到,则转交给 App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到 **指定的文件系统或网络等URL **中加载该类。

如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。

1 启动类加载器(引导类加载器,Bootstrap classLoader)#

1)这个类加载使用c/C++语言实现的,嵌套在JVM内部。
2)它用来加载Java的核心库(JAVA_HOME/jre/ lib/rt.jar、resources.jar或sun.boot.class.path路径下的内容),用于提供JVM自身需要的类。
3)并不继承自java.lang.classLoader,没有父加载器。加载扩展类和应用程序类加载器,并指定为他们的父类加载器。出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类。

2.2 扩展类加载器(Extension classLoader)#

1)Java语言编写,由sun.misc.Launcher$ExtClassLoader实现,派生于classLoader类。
2)父类加载器为启动类加载器。
3)从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的ire/lib/ext子目录(扩展目录)下加载类库。如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。

2.3 应用程序类加载器(系统类加载器,AppclassLoader)#

1)java语言编写,由sun.misc.Launcher$AppclassLoader实现。
2)派生于classLoader类,父类加载器为扩展类加载器。
3)它负责加载环境变量classpath或系统属性java.class.path指定路径下的类库。
4)该类加载是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载。
5)通过classLoader#getsystemClassLoader ()方法可以获取到该类加载器。

2.4 用户自定义类加载器(User Defined classLoader)#

1)在Java的日常应用程序开发中,类的加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方式。
2)主要功能:

隔离加载类、修改类加载的方式、扩展加载源防止源码泄漏

 

所以在spark加载类的过程中,会优先加载spark环境依赖的jar,之后在加载用户自行添加的jar

  

参考:Spark 如何摆脱java双亲委托机制优先从用户jar加载类?

Add JAR files to a Spark job - spark-submit

Spark 类加载器导致的Kryo序列化问题