JVM:3.Classloader

    虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验转换解析初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制.
类加载图示:
JVM:3.Classloader_第1张图片

初始化阶段:
对于初始化阶段,虚拟机规范则是严格规定了有且只有5种情况必须立即对类进行“初始化”:
1.遇到 new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化.
    •     new关键字实例化对象,
    •     读取或者设置一个静态变量,
    •     调用类的静态方法
2.使用java.lang.reflect包的方法对类进行 反射调用的时候
3. 父类没有被初始化时,先进行父类初始化
4.当虚拟机启动时,用户需要指定一个要 执行的主类(含有main方法的类)
5.JDK 1.7的 动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化)
示例:
    • 被动引用被初始化
                1.静态字段引用
                    JVM:3.Classloader_第2张图片

                2.数组引用
                    JVM:3.Classloader_第3张图片
    

                3.final静态字段引用

                JVM:3.Classloader_第4张图片

Note:接口的加载过程与类加载过程稍有一些不同,针对接口需要做一些特殊说明: 接口也有初始化过程,这点与类是一致的,上面的代码都是用静态语句块“static{}”来输出初始化信息的,而接口中不能使用“static{}”语句块,但编译器仍然会为接口生成“<clinit>()”类构造器[2],用于初始化接口中所定义的成员变量。接口与类真正有所区别的是前面讲述的5种“有且仅有”需要开始初始化场景中的第3种: 当一个类在初始化时,要求其父类全部都已经初始化过了,但是 一个接口在初始化时,并不要求其父接口全部都完成了初始化,只有在真正使用到父接口的时候(如引用接口中定义的常量)才会初始化
类加载器:
类加载器可以说是Java语言的一项创新,也是Java语言流行的重要原因之一,它最初是为了满足Java Applet的需求而开发出来的.
java中使用 双亲委派模式进行类加载.双亲委派如图所示:
                JVM:3.Classloader_第5张图片

    双亲委派模型的工作过程是如果一个类加载器收到了类加载的请求,它首先 不会自己去尝试加载这个类,而是 把这个请求委派给父类加载器去完成, 每一个层次的类加载器都是如此,因此所有的加载请求 最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载.
          在Java的世界中大部分的类加载器都遵循这个模型,但也有例外,到目前为止,双亲委派模型主要出现过3较大规模的 "反双亲"情况
  1. 双亲委派模型的第一次“被破坏”其实发生在双亲委派模型出现之前——即JDK 1.2发布之前。由于双亲委派模型在JDK 1.2之后才被引入,而类加载器和抽象类java.lang.ClassLoader则在JDK 1.0时代就已经存在,面对已经存在的用户自定义类加载器的实现代码,Java设计者引入双亲委派模型时不得不做出一些妥协。
  2.  双亲委派模型的第二次“被破坏”是由这个模型自身的缺陷所导致的,双亲委派很好地解决了各个类加载器的基础类的统一问题(越基础的类由越上层的加载器进行加载),基础类之所以称为“基础”,是因为它们总是作为被用户代码调用的API,但世事往往没有绝对的完美,如果基础类又要调用回用户的代码.eg:jndi jdbc等
  3. 双亲委派模型的第三次“被破坏”是由于用户对程序动态性的追求而导致的,这里所说的“动态性”指的是当前一些非常“热门”的名词:代码热替换(HotSwap)、模块热部署(Hot Deployment)、OSGI模块化编程等

你可能感兴趣的:(JVM:3.Classloader)