zoukankan      html  css  js  c++  java
  • Java Class Loader

    1.结束一个JVM生命周期的方式:
    System.exit()
    Normal finish done
    encounter the error or exception
    crash,出core
    操作系统问题或者硬件导致

    2.类加载的三个阶段:
    加载:查找并且加载类的二进制数据
    链接:--验证:确保被加载类的正确性
    --准备:为类的静态变量分配内存,并将其初始化为默认值
    --解析:把类的符号引用转换为直接引用
    初始化:为类的静态变量赋予正确的初始值

    3.所有的java虚拟机实现必须在每个类或者接口被java程序首次主动使用时才初始化他们,当然现代JVM有可能根据程序上下文语义推断出接下来可能初始化谁

    4.类的主动使用和被动使用
    主动使用:
    --new,直接使用
    --访问某个类或接口的静态变量,或者对该静态变量进行赋值操作
    a.对某个类的静态变量进行读写->class
    b.对接口中静态变量进行读取->interface
    --调用静态方法
    --反射某个类
    --初始化一个子类
    --启动类,比如java HelloWorld
    除了上述六个以外,其余的都是被动使用,不会导致类的初始化

    注意:(1)通过子类访问父类的static变量,不会导致子类的初始化
       (2)定义引用数组,不会初始化类
       (3)final修饰的常量会在编译期间放到常量池中,不会初始化类
       (4)final修饰的复杂类型,在编译期间无法计算得出,会初始化类

    5.类加载阶段详解:
    类的加载简单来说,就是将class文件的二进制数据读取到内存,将其放到方法区中,然后在堆区中创建一个java.lang.Class对象,
    用来封装在方法区的数据结构

    6.1类加载的最终产品是位于堆区中class对象
    6.2加载类的方式
    本地磁盘中直接加载
    内存中直接加载
    通过网络加载.class
    从zip,jar等归档文件中加载.class文件
    数据库中提取.class文件
    动态编译

    7.链接阶段
    在加载阶段完成后,虚拟机外部的二进制数据量就会按照虚拟机所需的格式存储在方法区中(数据结构),然后在堆区中创建一个class对象,这个对象
    作为程序访问方法区中这些数据的外部接口。
    加载阶段与链接阶段的部分内容是可以交叉进行的,比如一部分代码加载完成就可以进行验证,提高效率。
    7.1
    验证的主要目的是确保class文件中的字节流中包含的信息符合虚拟机的要求,并且不会损害到JVM自身的安全
    VerifyError
    文件格式验证:
    (1)魔术因子是否正确,OxCAFEBABE
    (2)主从版本号是否符合当前虚拟机
    (3)常量池中的常量类型是不是不支持
    (4)etc
    元数据验证:
    (1)是否有父类
    (2)父类是不是允许继承
    (3)是否实现了抽象方法
    (4)是否覆盖了父类的final字段
    (5)其他的语义检查
    字节码验证:
    主要进行数据流和控制流的分析,不会出现这样的情况,在操作栈中放置了一个int类型,但是却给了一个long型的数据
    符号引用验证:
    调用了一个不存在方法,字段等等
    符号引用验证的目的是确保解析动作能正常进行,如果无法通过符号引用验证,将会抛出一个 java.lang.IncompatibleClassChangeError异常的子类,如
    java.lang.IllegalAccessError、java.lang.NoSuchFieldError、java.lang.NoSuchMethodError等

    8.准备阶段
    准备阶段就是给类变量分配初始值

     

    9.解析阶段
    (1)类或接口的解析
    (2)字段解析
    (3)类方法解析
    (4)接口方法解析

    10.初始化阶段
    (1)类加载过程中的最后一步
    (2)初始化阶段是执行构造函数<clinit>()方法的过程
    (3)<clinit>()方法是由编译器自动收集类中的所有变量的赋值动作和静态语句块中的语句合并产生的
    (4)静态语句块中只能访问到定义在静态语句块之前的变量,定义在他之后的变量,只能赋值,不能访问
    (5)<clinit>()方法与类的构造函数有点区别,他不需要显示的调用父类的构造函数,虚拟机会保证在子类的<clinit>()执行之前,
    先执行父类的<clinit>,因此在虚拟机中首先被执行的是Object的<clinit>()方法
    (6)由于父类的<clinit>()方法要先执行,也就意味着父类中定义的静态语句块,要优先于子类
    (7)<clinit>()方法对于一个类来说并不是必须的
    (8)接口中照样存在<clinit>()方法
    (9)虚拟机有义务保证<clinit>()方法的线程安全

    注:<clinit>()方法即是static静态块

  • 相关阅读:
    java语法基础(总结)
    ZookeeperclientAPI之创建会话(六)
    对A轮的追逐变得越加狂热,当前距离互联网泡沫到底有多近?
    Java集合(一):Java集合概述
    深入了解Cookie(1)------selenium2进行Cookie操作的前奏
    Cocos2d-X开发中国象棋《九》走棋规则
    java中request,application,session三个域及参数简单示例
    在多浏览器使用JS复制内容到剪切板,无需插件
    初学structs2,结果类型简单示例
    使用servletAPI三种方式简单示例
  • 原文地址:https://www.cnblogs.com/zheaven/p/12190256.html
Copyright © 2011-2022 走看看