JVM02-类的加载连接与初始化过程

加载:将java的字节码文件加载到内存中。

Java对类的使用过分为两种

  • 主动使用
  • 被动使用

注意:所有的java虚拟机实现必须在每个类或者接口被Java程序 首次主动使用的时候才会被初始化

主动使用

Jvm字节码划分的主动使用和被动使用准确性更高,但是平时开发接触不多,所以粗略的分为以下几种:

  • 创建类的实例 即:new class
  • 访问某个类或者接口的静态变量,或者对该静态变量赋值
  • 调用类的静态方法
  • 反射,如Class.forName(“xx.xx.Test”)
  • 初始化一个类的子类。即如果我实例化了子类对象,此时我不仅会初始化当前子类,还会初始化其父类。即主动使用子类以及其父类,如果父类还有父类也会被实例化,直到最上层。
  • Java虚拟机启动时被标明该类为启动类的类,如类中含有main方法。
  • JDK 1.7开始提供动态语言的支持:java.lang.invoke.MethodHandle实例的解析结果REF_getStatic,REF_putStatic,REF_invokeStatic句柄所对应的类没有初始化,则初始化。(这个地方的句柄,我觉得可以理解为就是一种标识,这个句柄具有属性,它标识了类或者其他语句的作用,或者特性)
被动使用

除以上几种情况外,其他都为被动使用,在程序启动的时候不会被初始化。

注意:被动使用只是不会被初始化,但是也会被加载到内存总使用。

类的加载

指将.class文件中的二进制数据放入内存中,将其放在运行时数据区的方法区中,然后在内存中创建一个java.lang.Class对象用来封装描述类在方法区内的数据结构。这个原来也是反射思想的来源。我们可通过Class对象得到类中任意成员的内容。

1. 加载Class文件的方式

jvm并没有规定,一定要从那个地方加载类,比较常见的以下几种:

  • 从本地系统中直接加载
  • 通过网络下载.class文件
  • 从zip、jar等归档文件中加载.class文件。我们平时开发可以使用jar包中分装好的方法、工具类就是因为这个。
  • 从专有数据库中提取.class文件(这个至今还没遇到过)。
  • 将Java源文件动态编译为.class文件,这个一是动态代理会用到,还有就是我们一开始使用Jsp写web页面的时候用到了,Jsp最终会被转换为一个Servlet,而servlet是一个类,所以该servlet会被类加载,放到内存中,被我们使用。
代码示例
  • 当一个类初始化的时候,要求其全部父类已经全部初始化完毕
//父类
class   Parent {
    static String str = "hello I am parent static string";
    static {
        System.out.println("I am parent static method");
    }
}
//子类
class Child extends Parent {
    static {
        System.out.println("I am child static method");
    }
}

//测试
    public static void main(String[] args) {
        System.out.println(Child.str);
        System.out.println("--------------------------");
    }

在这里插入图片描述

//父类
class   Parent {
    static String str = "hello I am parent static string";
    static {
        System.out.println("I am parent static method");
    }
}
//子类
class Child extends Parent {
    static String str2 = "hello I am Child static string ";
    static {
        System.out.println("I am child static method");
    }
}

//测试
    public static void main(String[] args) {
        System.out.println(Child.str);
        System.out.println("--------------------------");
        System.out.println(Child.str2);
    }

在这里插入图片描述

  1. 对比上面两种结果,第一种,虽然是Child类调用的str静态变量,但是str静态变量实际上是Parent直接定义的,子类只是拿来用了以下,所以子类的Child静态代码块并没有被初始化。
  2. 第二种方式,Child调用了自己直接定义的str2,打印出来是Child的静态代码块被初始化

第二种有点不能说明问题,当吧main中调用Child.str去掉,在测试结果是:
在这里插入图片描述
这就体现出来,类的初始化是 父类–>子类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值