3、类的加载、连接与初始化过程详解

3.1、类的加载
  类的加载指的是将类的class文件中的二进制数据读入到内存中,将其放置在运行时数据区的方法区内,然后在内存中创建一个java.lang.Class对象(规范并未说明Class对象放在哪里,HotSpot虚拟机将其放在了方法区中),用来封装类在方法区内的数据结构。
  注意:一个类不管创建了多少实例,这些实例对应的Class对象只有一个
  加载.class文件的几种方式
    从本地系统中直接加载(最常使用,.class文件位于类路径下面)
    通过网络下载.class文件
    从zip,jar等归档文件中加载.class文件
    从专有数据库中提取.class文件
    将java源文件动态编译为.class文件(动态代理,web开发中jsp转换为servlet)

  可以通过配置jvm参数(-XX:+TraceClassLoading)打印出类的加载信息

    jvm参数简介:

      都以“-XX:”打头,共有3大类:

        -XX:+<option>:表示开启option选项
        -XX:-<option>:表示关闭option选项
        -XX:<option>=<value>:表示将option选项的值设置为value

    举例:
      -XX:+TraceClassLoading  开启追踪类的加载信息并打印出来
      -XX:-TraceClassLoading   关闭追踪类的加载信息并打印出来

3.2、类的连接
  参考2.2章节

3.3、类何时被初始化

  所有的java虚拟机实现必须在每个类或接口被java程序【首次主动使用】时才初始化他们

  java程序对类的使用方式分为2种,主动使用和被动使用。

-主动使用(7种)
  1)创建类的实例,如创建一个学生对象new Student(),注意,创建一个学生的数组对象new Student[1]并不属于主动使用范畴,不会引起类的初始化
  2)访问某个类或接口的静态变量,或者对该静态变量进行赋值
  3)调用类的静态方法
  4)反射(Class.forName("com.shtec.Test"))
  5)初始化一个类的子类
  6)java虚拟机启动时被标记为启动类的类(包含main方法的那个类)
  7)JDK1.7开始提供的动态语言支持(了解)
    java.lang.invoke.MethodHandle实例的解析结果REF_getStatic,REF_putStatic,REF_invokeStatic句柄对应的类没有初始化,则初始化

  2)、3)对应的 助记符
  访问静态变量       getstatic
  对静态变量赋值    putstatic
  调用静态方法     invokestatic

案例:

package com.shtec.init;

/**
 * 对于静态字段来说,只有直接定义了该字段的类才会被初始化。子类调用父类的静态字段并不会引起子类的初始化
 * 当一个类在初始化时,会先初始化它的父类。
 * 
 * 注意:类是否被初始化并不影响类的【加载】过程
 *         虚拟机参数: 
 *             -XX:+TraceClassLoading 用于追踪类的加载信息并打印出来
 * @author sunhao
 *
 */
public class Demo {
    
    public static void main(String[] args) {
        //对于静态字段来说,只有直接定义了该字段的类才会被初始化。子类调用父类的静态字段并不会引起子类的初始化
        System.out.println(Child.a);
        //输出如下:
        //Parent static block
        //parent
        
        //当一个类在初始化时,会先初始化它的父类。
        System.out.println(Child.b);
        //输出如下:
        //Parent static block
        //Child static block
        //child
    }
}

class Parent{
    public static String a = "parent";
    static{
        System.out.println("Parent static block");
    }
}

class Child extends Parent{
    public static String b = "child";
    static{
        System.out.println("Child static block");
    }
}

  -被动使用

    除了以上7种情况,其他使用java类的方式都被看作是对类的【被动使用】,都不会导致类的初始化

 

posted @ 2020-02-18 17:59  java小天地  阅读(523)  评论(0编辑  收藏  举报