类加载机制详解

常见类加载器:BootstrapClassLoader/ExtClassLoader/AppClassLoader/URLClassLoader/WebappClassLoader。html

BootstrapClassLoader(启动类加载器):主要加载JVM自身工做须要的类,彻底由JVM本身控制;它是全部类加载器的父加载器,位于jre/lib/rt.jar。java

ExtClassLoader(扩展类加载器):它既装载除了基本的Java API之外的扩展类,也负责装载其余的安全扩展功能;位于System.getProperty("java.ext.dirs")指向的目录。bootstrap

AppClassLoader(系统类加载器):负责加载用户在$CLASSPATH里指定的类,位于System.getProperty("java.class.path")。安全

User-defined ClassLoader(用户自定义类加载器):直接用代码实现的类加载器,如:WebappClassLoader。app

 

类是如何被加载的?   它们使用双亲委派的模型来加载;基于三个机制:委托、可见性和单一性。this

委托:当一个类加载和初始化的时候,类仅在有须要加载的时候被加载。首先加载这个类的请求由AppClassLoader委托给它的父类加载器ExtClassLoader,而后再委托给BootstrapClassLoader。BootstrapClassLoader会先看看rt.jar中有没有这个类,若是并无这个类,就把这个请求返回到ExtClassLoader,它会查看jre/lib/ext目录下有没有这个类,若是这个类被ExtClassLoader找到了,那么它将被加载,而AppClassLoader不会加载这个类;而若是这个类没有被ExtClassLoader找到,那么再由AppClassLoader从classpath中寻找。spa

可见性:子类加载器能够看到父类加载器加载的类,而反之则不行。.net

单一性:父加载器加载过的类不能被子加载器加载第二次。htm

 

class的加载方式?对象

隐式加载:不经过调用ClassLoader来加载须要的类,而是经过JVM自动加载所需的类到内存。如,继承与类引用。

显示加载:经过ClassLoader类来加载类的方式。如,this.getClass().getClassLoader().loadClass()/Class.forName()/自定义的类加载器的findClass()。

Class.forName(),ClassLoader.loadClass()的区别

http://blog.csdn.net/qq_27093465/article/details/52262340

 

自定义类加载器?

本身定义的类加载器通常继承ClassLoader/URLClassLoader。

通常只须要重写findClass()方法;

同一个类若是被两个类加载器加载,那么JVM不认为使相同的类;

检查被请求的类是否已经被加载到命名空间,若是已被加载,则直接返回。

若是想打破双亲委派模型,那么就重写整个loadClass方法

https://www.cnblogs.com/szlbm/p/5504631.html

JDK中的ClassLoader实现的:

先先查找.class是否被加载过,若是.class文件没有被加载过,那么会去找加载器的父加载器。

父加载器开始尝试加载.class文件,加载成功就返回一个java.lang.Class,加载不成功就抛出一个ClassNotFoundException,给子加载器去加载。

 

双亲委派机制

一、类的加载过程采用委托模式实现

二、每一个 ClassLoader 都有一个父加载器。

三、类加载器在加载类以前会先递归的去尝试使用父加载器加载。

四、虚拟机有一个内建的启动类加载器(bootstrap ClassLoader),该加载器没有父加载器,可是能够做为其余加载器的父加载器。

双亲委派机制能很好地解决类加载的统一性问题。

JVM在断定两个class是否相同时,不只要判断两个类名是否相同,并且要判断是否由同一个类加载器实例加载的。只有二者同时知足的状况下,JVM才认为这两个class是相同的。

对一个 Class 对象来讲,若是类加载器不一样,即使是同一个字节码文件,生成的 Class 对象也是不等的。也就是说,类加载器至关于 Class 对象的一个命名空间。

双亲委派机制则保证了基类都由相同的类加载器加载,这样就避免了同一个字节码文件被屡次加载生成不一样的 Class 对象的问题。

但双亲委派机制仅仅是Java 规范所推荐的一种实现方式,它并非强制性的要求。近年来,不少热部署的技术都已不遵循这一规则,如 OSGi 技术就采用了一种网状的结构,而非双亲委派机制。

http://www.cnblogs.com/paddix/p/5268559.html

 

 

classloader加载一个类的过程分为4步:

  • 第一步,从某个地方获得咱们想要的字节码二进制流;

  • 第二步,读入字节码流并转化为Class;

  • 第三步,连接;

  • 第四步,初始化。

ClassLoader 提供了另外一个方法 findClass 来完成第一步,

而后调用ClassLoader提供的defineClass来完成第二步,

ClassLoader提供了resolveClass方法完成第三步连接的工做

https://mp.weixin.qq.com/s/qHTXwS4BdI2gKwPzQK-D6g

    

Class.forName和ClassLoader.loadClass区别:

    第一,ClassLoader.loadClass能够显式指定装载class的ClassLoader,可是Class.forName就不行了,他会默认使用调用类的ClassLoader来装载class。

    第二,ClassLoader.loadClass仅仅加载class进来,可是不会初始化类,而Class.forName不只会加载class并且还会初始化类。

https://blog.csdn.net/liweisnake/article/details/8857744

https://blog.csdn.net/u011202334/article/details/51497998

 

 

http://blog.csdn.net/xyang81/article/details/7292380#10006-weixin-1-52626-6b3bffd01fdde4900130bc5a2751b6d1

相关文章
相关标签/搜索