zoukankan      html  css  js  c++  java
  • 7. 类加载机制 7.1 类的加载、连接、初始化

    类加载机制概述:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成可以被虚拟机直接使用的java类型,这就是java虚拟机的机制

    1. Java程序执行时遵循以下顺序

      1.1. 加载:将类的.class文件中的二进制数据装载到内存中,将其放在运行时数据区方法区内,然后在堆区创建一个java.lang.Object对象,用来封装类在方法区的数据结构

        1.1.1. 加载.class方式:

          1.1.1.1. 从本地系统中加载

          1.1.1.2. 通过网络下载.class

          1.1.1.3. 从zip、jar等文件中加载.class

          1.1.1.4. 从数据库中提取.class

          1.1.1.5. 将Java源文件动态编译成.class

      1.2. 连接:

        1.2.1. 验证:确保被加载的类的正确性(防止恶意用户手工构造.class文件)

          1.2.1.1. 类文件的结构检查:确保类文件遵从Java类文件的固定格式

          1.2.1.2. 语义检查:确保类本身符合Java语言的语法规则(例如:final类型的类没有子类)

          1.2.1.3. 字节码验证:确保字节码流(包括静态方法和实例方法)能被Java虚拟机安全执行

          1.2.1.4. 二进制兼容性验证:确保相互应用的类之间协调一致(例如:NosuchMethodError)

        1.2.2. 准备:为类的静态变量分配内存,并将其初始化为默认值

        1.2.3. 解析:把类中的符号引用转换为直接引用:

    public class Car{
       public void run(){}   
    }
    
    public class Worker{
       public void work(){
           Car car = new Car();
           car.run();   //这段代码在Worker类的二进制数据中表示为符号引用
       }   
    }
    在Worker类的二进制数据中,包含了一个对Car类的run()方法的符号引用,它由run()方法的全名和相关描述组成。
    解析阶段,Java虚拟机会把这个符号引用替换为一个指针,该指针指向Car类的run()方法在方法区内的内存位置,这个指针就是直接引用

      1.3. 初始化:为类的静态变量赋予正确的初始值

        1.3.1. 静态变量初始化方式:

          1.3.1.1. 在静态变量声明处初始化

          1.3.1.2. 在静态代码块中初始化

    Notice : 准备的初始化为默认值与初始化赋予正确的初始值不是一个意思

    public class Student {
        private static int a = 1;
    }

    准备阶段,a的默认值是0,初始化的阶段a才等于3

    上面这个过程等同于以下代码:

    public class Student {
        private static int a;
        static{
            a = 3;  
        }   
    }

    2. 只有静态变量在准备阶段才被初始化,那么类在什么时候初始化呢?

    public class Handsome{
      public static int a =1;     
      public static void sayHi(){}   
    }
    
    public class Child extends Handsome{
      private static int b = 2;   
    public static void main(String [] args){
        Child.b = 3;
      } }

    Java程序对类的使用方式分为两种:

      1.1. 主动使用(6种)

        1.1.1:创建类的实例 --> new Handsome()

        1.1.2:访问某个类或接口的静态变量,或者对该静态变量赋值 --> Handsome.a = 2

        1.1.3:调用类的静态方法 --> Handsome.sayHi()

        1.1.4:反射 --> Class.forName("Handsome")

        1.1.5:初始化一个类的子类 --> Child.b = 3

        1.1.6:Java虚拟机启动时被标明为启动类的类 --> 含main方法启动的类

      1.2. 被动使用: 除开上面6种的其他方式,都不会导致类被初始化

    3. 每个类或接口被Java程序“首次主动使用”时才初始化

    下一篇:7.2类加载器

  • 相关阅读:
    【题解】字母 (letter)
    【题解】【原创题目】薇尔莉特
    【题解】Query on a tree III [SP1487] [Bzoj1803]
    11个炫酷的 Linux 终端命令
    A light-weight client-side OAuth library for Java
    android下的异步任务
    OAuth相关知识
    显示单位px、dip以及sp的区别
    Arduino连接SHT10温湿度传感器--返回值不正常解决办法
    blueterm蓝牙超级终端(源码)
  • 原文地址:https://www.cnblogs.com/wangfajun/p/9341312.html
Copyright © 2011-2022 走看看