类加载过程

作者: Gason_d796 | 来源:发表于2020-02-17 21:33 被阅读0次

类的加载过程

加载

  • 通过一个类的全限定名获取此类的二进制字节流
  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据据结构
  • 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问入口
加载.class文件的方式
  • 从本地系统中直接加载
  • 通过网络获取
  • 从zip压缩包中读取,成为日后jar,war格式的基础
  • 运行时计算生成,使用最多的是:动态代理
  • 有其他文件生成(JSP)
  • 从数据库中提取
  • 从加密文件中获取(防止反编译)

链接

验证
  • 目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全
  • 主要包括四种验证:文件格式验证,元数据验证,字节流验证,符号引用验证
准备
  • 为类变量分配内存并且设置该类变量的默认初始值,即零值
  • 这里不包含用final修饰的static,因为final在编译的时候就会分配了,准备阶段会显式初始化
  • 这里不会为实例变量分配初始化,类变量会分配在方法区,而实例变量是会随着对象一起分配到Java堆中去
解析
  • 将常量池内的符号引用转换为直接引用的过程
  • 事实上,解析操作往往会伴随着JVM在执行完初始化之后再执行
  • 解析动作主要针对类或接口,字段,类方法,接口方法,方法类型等。对应常量池中的CONSTANT_Class_info等

初始化

  • 初始化阶段就是执行类构造器方法<clinit>()的过程
  • 此方法不需定义,就是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来
  • 构造器方法中指令按语句在源文件中出现的顺序执行。
public class ClassInitTest {
    private static int num = 1;

    static {
        num = 2;
        number = 20;
        System.out.println(number);// 会报错:非法的前向引用
    }

    private static int number = 10; // 链接的准备阶段:number=0 -->初始化<clinit>()按顺序依次:20 -->10

    public static void main(String[] args) {
        System.out.println(ClassInitTest.num);// 2
        System.out.println(ClassInitTest.number); // 0
    }
}
  • <clinit>()不同于类的构造器(构造器是虚拟机反编译后的<init>()方法),当没有静态变量时或静态代码块,就不会存在
  • 若该类具有父类,JVM会保证父类的<clinit>()执行完成后,再执行子类的<clinit>()
public class ClassInitTest {
    static class Father {
        public static int A = 1;

        static {
            A = 2;
        }
    }

    static class Son extends Father {
        public static int B = A
    }

    public static void main(String[] args) {
        System.out.println(Son.B);// 2
    }
}
  • 虚拟机必须保证一个类的<clinit>()方法在多线程下被同步执行
public class ClassInitTest {
    public static void main(String[] args) {
        Runnable r = () -> {
            System.out.println(Thread.currentThread().getName() + "开始");
            DeadThread deadThread = new DeadThread();
            System.out.println(Thread.currentThread().getName() + "结束");
        };
        Thread t1 = new Thread(r, "线程1");
        Thread t2 = new Thread(r, "线程2");
        t1.start();
        t2.start();
    }

    class DeadThread {
        static {
            if (true) {
                System.out.println(Thread.currentThread().getName() + "初始化DeadThread");
                while (true) {

                }
            }

        }
    }
}

结果是只能输出一次 ‘初始化DeadThread’,如果初始化阻塞,会影响其他类无法使用该类

相关文章

  • 第一章 类加载过程

    要点 类加载过程 类加载器 一、类加载过程 1.类的加载过程 类的加载 .class文件过程分为:加载---->连...

  • JVM总括四-类加载过程、双亲委派模型、对象实例化过程

    JVM总括四-类加载过程、双亲委派模型、对象实例化过程 目录:JVM总括:目录 一、 类加载过程 类加载过程就是将...

  • 2019年JVM面试都问了什么?快看看这22道面试题!(附答案解

    一. Java 类加载过程? Java 类加载需要经历一下 7 个过程: 1. 加载 加载是类加载的第一个过程,在...

  • 面经题目学习

    java类加载过程类加载过程:加载、验证、准备、解析、初始化。类加载过程中主要是将Class文件(类的二进制字节流...

  • jvm相关面试题

    类加载的过程 classLoader.loadClass的类加载过程有如下几步:加载 >> 验证 >> 准备 >>...

  • 类加载过程--加载

    类从加载到虚拟机内存中开始,到卸载出内存为止的步骤如下:http://www.jianshu.com/p/66ec...

  • JVM-类加载器

    类加载器 类加载器是用来把类加载到JAVA虚拟机中。 类加载的过程 类的加载过程采用了父亲委托的机制,这种机制能更...

  • 01-类加载过程

    类加载过程 类加载可以分为加载、连接、初始化3个部分 加载 加载过程是指查找并加载类的二进制数据,加载class文...

  • jvm(二)类加载过程与类加载器

    本篇内容: 类加载过程 类加载器分类 双亲委托机制 沙箱安全机制 类加载过程 类加载器子系统负责将从文件系统或者网...

  • Java类加载问题

    类加载过程类加载过程:加载->连接->初始化。连接过程又可分为三步:验证->准备->解析。一个非数组类的加载阶段(...

网友评论

    本文标题:类加载过程

    本文链接:https://www.haomeiwen.com/subject/xvyifhtx.html