类加载

Klass模型

java中的类,在jvm中都有一个对应的Klass类实例与之对应。存储类的元信息: 

常量,成员属性,方法

类的元信息都在元空间

普通的java类在jvm对应的是InstanceKlass实例

它有三个子类:

  •  InstanceMirrorKlass:用于表示java.lang.Class对象。实际上是c++类的实例,存放在堆区。也叫镜像类
  • InstanceRefKlass:用于表示java/lang/ref/reference的子类
  • InstanceClassLoaderKlass:用于表示遍历某个加载器加载的类

java中的数组不是静态数据类型,是动态数据类型,既运行时期。java中的数组元信息是由ArrayKlass子类表示

  • TypeArrayKlass:表示基本类型的数组
  • ObjArrayKlass:表示引用类型的数组

 

类加载的过程

类加载是有7个步骤组成,但是类的加载只有前面5个

加载

  • 通过类的全限类名获取class文件
  • 解析成运行时数据既InstanceKlass实例
  • 在堆区生成该类的calss对象,既:InstanceMirrorKlass实例

那么什么时候加载?

主动使用

  1. 遇到new,getstaic,pubstatic或者invokestatic字节码指令
  2. 反射
  3. 初始化一个类的子类回去加载父类
  4. 启动类(main函数所在的类)
  5. 当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic,REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化

例子:

 

 

预加载:包装类,String,Thread

从那里获取class文件?

  1.   从压缩包中读取,如jar,war
  2. 从网络中获取,如web applet
  3. 动态生成动态代理,cglib
  4. 从数据库读取
  5. 从加密文件

 

验证

  1. 文件格式验证
  2. 元数据验证
  3. 字节码验证
  4. 符号引用验证

准备

为静态变量分配内存,赋予初值。实例变量是在创建对象时候完成赋值,没有赋初值一说

image.png

通常情况下初始值是零值,如果被final修饰,在编译的视乎会给属性添加ConstantValue属性,准备阶段直接完成赋值,没有赋予初值这一步

 

解析

将常量池的符号引用转化为直接引用

符号引用:指向运行时常量池的引用

直接引用:指向内存地址

解析后的信息存储在ConstantPoolCache类实例中

1.类或者接口的解析

2.字段解析

3方法解析

4.接口解析

何时解析?

1.加载阶段解析常量池时

2.用的时候

 

初始化

执行静态代码块,完成静态变量的赋值

静态字段,静态代码快,字节码层面或生产clinit方法

方法中语句的先后顺序与代码的编写顺序有关

简而言之:初始化阶段就是执行类构造器clinit方法的过程,它是由编译器自动收集类中的所有类变量的赋值动作和static中的语句合并产生的。


/**
 * 结果:
 *      1
 *      2
 */

public class Test_21 {

    public static void main(String[] args) {
        Test_21_A obj = Test_21_A.getInstance();

        System.out.println(Test_21_A.val1);
        System.out.println(Test_21_A.val2);
    }
}

class Test_21_A {

    public static int val1;


    public static Test_21_A instance = new Test_21_A();

     Test_21_A() {
        val1++;
        val2++;
    }
    public static int val2 = 1;
    public static Test_21_A getInstance() {
        return instance;
    }
}

  准备阶段:val1=0,instance=null,val2=0;

初始化阶段:clinint(){

val1=0;

val1=0+1=1;

val2=1;

 

val2=1执行两次覆盖

                 


public class Test_21 {

    public static void main(String[] args) {
        Test_21_A obj = Test_21_A.getInstance();

        System.out.println(Test_21_A.val1);
        System.out.println(Test_21_A.val2);
    }
}

class Test_21_A {

    public static int val1;
    public static int val2 = 1;

    public static Test_21_A instance = new Test_21_A();

     Test_21_A() {
        val1++;
        val2++;
    }

    public static Test_21_A getInstance() {
        return instance;
    }
}

准备阶段:val1=0,val2=0,instance=null

初始化:clinit(){

val1=0,val2=1

val1=0+1=1;

val21=1+1=2

}


public class Test_10 {
    public static void main(String[] args) {
        System.out.printf(Test_10_B.str);
    }
}

class Test_10_A {
    public static String str = "A str";

    static {
        System.out.println("A Static Block");
    }
}

class Test_10_B extends Test_10_A {
    static {
        str += "#11";

        System.out.println("B Static Block");
    }
}

A Static Block
A str

优先加载父类

public class Test_9 {

    public static void main(String[] args) {
        System.out.printf(new Test_9_B().str);
    }
}

class Test_9_A {

    static {
        System.out.println("A Static Block");
    }
}

class Test_9_B extends Test_9_A {
    public String str = "A str";

    static {
        System.out.println("B Static Block");
    }
}

A Static Block
B Static Block
A str


public class Test_6 {

    public static void main(String[] args) {
        System.out.println(Test_6_A.str);
    }
}

class Test_6_A {
    public static final String str = "A Str";

    static {
        System.out.println("Test_6_A Static Block");
    }
}

final修饰准备阶段就已经被初始化微ConstantValue属性所指定的初始值

A Str

public class Test_4 {

    public static void main(String[] args) {
        Test_4 arrs[] = new Test_4[1];
    }
}

class Test_4_A {
    static {
        System.out.println("Test_4_A Static Block");
    }
}

通过数组定义来应用类,不会触发此类的初始化


public class Test_2 {

    public static void main(String[] args) {
        System.out.printf(Test_2_B.str);
    }
}

class Test_2_A {
    static {
        System.out.println("A Static Block");
    }
}

class Test_2_B extends Test_2_A {
    public static String str = "B str";

    static {
        System.out.println("B Static Block");
    }
}

A Static Block
B Static Block
B str

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值