classloader分类
启动类装载器
扩展类装载器
应用装载器
启动类装载器加载java基本api相关的类。
扩展装载器加载JAVA_HOME/jre/lib/ext目录下的class文件
应用装载器加载应用程序相关jar包及程序相关class
启动顺序
启动类装载器---->扩展类装载器---->应用装载器
类装载器执行
类装载采用双亲委托模式,即应用装载器请求它的父装载器(扩展装载器),扩展装载器请求它的父装载器(启动装载器),顶层的装载器一定是启动类装载器,如果父装载器不能返回所需类,就由自己来加载。
类装载器的安全机制
jvm可以有多个classloader,每一个classloader都有一个名称空间唯一标识,只有同一个名称空间内的类采可以相互访问。
如果非启动类装载器试途装载java.lang.Integer类,该操作将被jvm取消,因为Integer经过由启动类装载器装载。
如果某个classloader试途装载一个恶意的class,如java.lang.Virus,该类在相关的父classloader中没有,所以将成功装载,问题是该类位置java.lang包中,这是非常危险的,这表明它可以访问java.lang中的相关类,但是classloader的名称空间不同virus还是不可以访问java.lang中的类,也就是说对于用户级的classloader加载的类只会拥有在同一个classloader同一个包的访问权限。
classloader还有一个安全域的概念,即classloader将被加载的类放入一个安全域中,安全域决定该类在运行时的权限。
相关api
获得boot classloader
sun.misc.Launcher.getBootstrapClassPath()
获得应用classloader
ClassLoader.getSystemClassLoader()
获得扩展classloader
ClassLoader.getSystemClassLoader().getParent()
用户可以自定义classloader
自定义ClassLoader需要继承ClassLoader抽象类,重写findClass方法,这个方法定义了ClassLoader查找class的方式。
主要可以扩展的方法有:
findClass 定义查找Class的方式
defineClass 将类文件字节码加载为jvm中的class
findResource 定义查找资源的方式
如果嫌麻烦的话,我们可以直接使用或继承已有的ClassLoader实现,比如
java.net.URLClassLoader
java.security.SecureClassLoader
java.rmi.server.RMIClassLoader
sun.applet.AppletClassLoader
Extension ClassLoader 和 App ClassLoader都是java.net.URLClassLoader的子类。
这个是URLClassLoader的构造方法:
public URLClassLoader(URL[] urls, ClassLoader parent)
public URLClassLoader(URL[] urls)