zoukankan      html  css  js  c++  java
  • 《Java高并发编程详解-多线程架构与设计》Java Classloader

    摘自《Java高并发编程详解-多线程架构与设计》第九章 p144-p157
    Java语言规范

    重点:

    1. 连接-准备阶段为静态变量赋初值,初始化阶段为静态变量赋代码值
    2. 引起初始化阶段的6种情况(主动引用),静态变量/方法,new,反射,子类引起父类。
    3. 被动引用,如静态常量。其值copy到被引用的类。
    4. 类加载的三个阶段
    5. 静态代码块可以对后面的静态变量赋值,但不能访问。
    6. clinit线程安全

    1.类加载的三个过程-简述

    1. 加载阶段
      查找并加载class文件
      loadClass from somewhere -> getClassBytes and defineClass->return Class
      常见异常:ClassNotFoundException,NoClassDefFoundError

    2. 连接阶段
      a. 验证
      确保类文件正确性。如class版本,魔数 CAFEBABE
      b. 准备-赋初始值
      为类的静态变量 分配内存,初始化【默认值】。
      c. 解析
      将类中符号引用转为直接引用。
      如引用了其他类, 则其他类先要经历类的所有加载过程。

    3. 初始化阶段 <clinit>()-赋代码值
      class initailze为类的静态变量赋予正确的值(代码编写时指定的值)

    2. 类的主动使用和被动使用

    JVM虚拟机规定,类和接口被java程序首次主动使用才会对其进行初始化。

    主动使用的场景-new,反射,使用静态部分,子导致父初始化

    1. new
    2. 访问类的静态变量
    3. 访问类的静态方法
    4. 对类进行反射操作 。 如 Class.forName(“xx”); 参考java.sql.driver初始化驱动时调用DriverManager注册driver。ps:ClassLoader.loadClass不会触发【连接-初始化阶段】,只会触发【加载阶段】。
    5. 初始化子类导致父类的初始化
      同理, 调用子类的静态变量会导致父类的初始化。

    在这里插入图片描述
    6. 启动类:执行main锁在的类会导致该类的初始化

    在这里插入图片描述

    除了上述6种,其他的都为被动使用,不会导致类的【加载】和【初始化】。

    在这里插入图片描述

    被动使用

    1. 引用类的静态常量
      ps:静态常量会在编译期间被计算出来copy到其他类,可使用javap查看class文件

    2. 声明数组

    3. 类的加载过程详解

    例子
    在这里插入图片描述

    在这里插入图片描述

    3.1 类的加载阶段

    关键:1.得到class对应的二进制流(不限方式)2.defineClass

    类的加载最终产物是堆内存中的class对象,对于同一个classLoader,不管加载多少次,对应到堆内存中的class是同一个(from cache)。
    所以可以使用不同的classLoader加载同名的不同类

    虚拟机规范规定类的加载是通过全限定名(包名+类名)来获取二进制数据流。
    调用loadClass->findClass->getClassBytes+defineClass

    常见的是class二进制文件形式,但可以是以下:

    1. 运行时动态生成,如ASM ,jdk动态代理,CGLIB
    2. 网络获取
    3. 读取zip获得类的二进制字节流,如war,jar。
      war,jar使用的是和zip一样的压缩算法。
    4. 将类的二进制文件储存在数据库的BLOB字段类型中。
    5. 运行时生成class文件,并动态加载,如Thrift/AVRO可以在运行时将schema文件生成对应的class文件再加载。

    3.2 类的连接阶段

    验证

    文件格式:确保类文件正确性。如class版本,魔数 CAFEBABE,MD5比对(class末尾)等。

    元数据:确保class符合jvm规范。语义验证。

    字节码:…
    符号引用:…

    准备

    为类的静态变量 分配内存,初始化默认值。
    如 static int a = 10; 在【准备阶段】a是0而不是10。
    如final static int b = 10; 注意,final static变量是【被动引用】,在编译期间即直接赋予了10;
    在这里插入图片描述

    在这里插入图片描述

    解析

    将类中符号引用转为直接引用。
    在常量池中寻找类、接口、字段、方法的符号引用,将其替换成直接引用。
    在这里插入图片描述

    初始化

    在这里插入图片描述
    ()保证顺序,对后面的静态变量只能赋值不能访问
    在这里插入图片描述

    类加载过程实例剖析

    在这里插入图片描述

    发布于2019年7月14日 20:24:54

  • 相关阅读:
    shell脚本编程练习
    linux中()、[]、{}、(())、[[]]等各种括号的使用
    Linux Shell 变量自加
    while read line [linux] shell 学习
    踢出某正在访问的用户||永久禁止某IP访问
    linux设置 自定义脚本开机启动
    syntax error: unexpected end of file完美解决方案
    Linux利用nc命令脚本批量检测服务器指定端口是否开放
    41-贪心算法
    38-动态规划
  • 原文地址:https://www.cnblogs.com/thewindkee/p/12873123.html
Copyright © 2011-2022 走看看