JVM---类加载机制

类加载机制

  • 1.类加载的时机
  • 2.类加载的过程
    • 1.加载
    • 2.验证
    • 3.准备
    • 4.解析
    • 5.初始化
  • 3.类加载器
    • 双亲委派模型

这篇文章说一下类加载机制

1.类加载的时机

类的生命周期是什么呢?是从被虚拟机加载到内存到卸出内存为止的一段过程。在这一段过程中,又细分为:加载,验证,准备,解析,初始化,使用和卸载7个阶段。
加载—>(验证,准备,解析)连接—>初始化—>使用—>卸载
这些阶段的顺序通常都是交叉进行的,所以顺序不能完全保证。
什么时候触发加载这个阶段,虚拟机规范中并没有给出强制的约束,虚拟机自行把握实现。
什么时候触发初始化这个阶段,虚拟机规范中严格规定了四种情况,必须对类进行“初始化“。
(1)使用new,getstatic,putstatic,invokestatic这4条字节码指令的时候,如果类没有进行过初始化,则需要触发其初始化。具体的代码场景是:使用new关键字实例化对象的时候,读取或设置一个类的静态字段时,以及调用一个类的静态方法时。
(2)对类进行反射调用时,如果类没有进行过初始化,则需要先触发其初始化。
(3)当初始化一个类时,如果发现其父类还没有初始化,则先初始化父类。
(4)虚拟机启动的时候,需要指定一个main类,包含main()方法的类,虚拟机会先初始化这个类。
这四种情况称为对类的主动引用,其余任何情况称为被动引用,而被动引用都不会触发初始化。

2.类加载的过程

1.加载

在这个阶段,完成三件事情:
(1)通过一个类的全限定类名来获取定义此类的二进制字节流
(2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
(3)在堆中生成一个代表这个类的Class对象,作为方法区这些数据的访问入口。

2.验证

验证是虚拟机对自身保护的一项重要操作。

3.准备

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。
类变量:被satic修饰的变量。
实例变量:会在对象实例化时随着对象一起分配在java堆上。
而且需要注意的是通常情况下为类变量赋值是初始值,并不是最终值。
比如 public static int a =1;准备阶段过后a的值是0,还没有变成1.
但是如果被final修饰,就直接是最终值1,public static final int a =1;

4.解析

5.初始化

初始化阶段是类加载阶段的最后一个阶段。在前边的阶段中,完全是由虚拟机去主导和控制的。这个阶段变是真正执行类中定义的java代码。
有一段很好的例子,如果弄明白这个知识点也就清楚了

public class Alibaba {

    public static int k = 0;//1.k =0
    public static Alibaba t1 = new Alibaba("t1");
    public static Alibaba t2 = new Alibaba("t2");
    public static int i = print("i"); //2  1:i i=0 n=99
    public static int n = 99;// n =99

    private int a = 0;
    public int j = print("j");
    {
        print("构造块");
    }
    static {
        System.out.println("静态代码块");
        print("静态块");
    }

    public Alibaba(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;
    }

    public static int print(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++n;
        return ++i;
    }

    public static void main(String args[]) {
        Alibaba t = new Alibaba("init");
    }
}

经过加载和连接流程后,进入初始化阶段,该阶段会对static域进行初始化。
首先k被赋值为0,接下来是t1,由于这时Alibaba类已经处于初始化阶段了,static无需再次初始化,否则会导致static域多次初始化情况,所以暂时忽略static域初始化操作,对非static域进行初始化操作。

3.类加载器

类加载器的作用是实现类的加载阶段。对于任意一个类,都需要由加载它的类加载器和这个类本身一同确定在java虚拟机中的唯一性。

双亲委派模型

打破双亲委派模型。

你可能感兴趣的:(JVM)