JVM_类加载机制

java文件想要被jvm识别首先要被转化成class文件,class文件是一个16进制的文件

当java文件转化成class文件后就会出现一个问题,是jvm主动获取这个class文件还是class文件自己进入jvm。 

jvm就出现了类加载机制。 

类加载机制就是jvm主动去获取文件夹中的类。

主动获取的条件:

1.外部调用这个类,读取内部的final和static变量

2.new一个对象

3.调用静态方法

类加载机制的步骤

Loading , linking, initialzing

(1) 装载 loading :各个类装载器扫描自己负责的文件夹下(创建class常量池和运行时常量池)

类装载器

   启动类加载器(Bootstrap classLoader):又称为引导类加载器,由C++编写,无法通过程序得到。主要负责加载JAVA中的一些核心类库,主要是位于<JAVA_HOME>/lib/rt.jar中。

     拓展类加载器(Extension classLoader):主要加载JAVA中的一些拓展类,位于<JAVA_HOME>/lib/ext中,是启动类加载器的子类。

     应用类加载器(System classLoader):    又称为系统类加载器,主要用于加载CLASSPATH路径下我们自己写的类,是拓展类加载器的子类。


但是又会出现一个问题,当各自文件夹下面都有一个 java.lang.String 文件时。这个类加载器会如何加载。

双亲委派

三个类加载器实际上属于继承关系,

classLoader(){

//先交给自己的父类来扫描,如果扫描到了这个类,装载然后结束

//父类没有扫描到则交给子类来扫描,扫描到了装载然后结束

//如果没有扫描到,抛出 异常

}

想要破环这个双亲委派,简单的就是重写这个classLoader方法。

(2)链接 linking:准备:分配方法区空间,主要是类变量(static修饰的)并设置初始值。(创建了全局字符串池)

        检查:确保被加载类的正确性

          解析:将符号引用转化为直接引用

(3)初始化 init : 类变量的赋值和static代码块的执行。

                     子类的初始化是从父类开始的,父类的静态代码块和类变量赋值--->子类的静态代码块和类变量赋值

  类会在外部主动调用的时候进行初始化步骤:

  1. 类的实例化(new,反射等)

  2.    调用类的静态方法

  3.    调用类或者某个接口的静态变量

  4.    子类进行了初始化

  5.    调用反射,Class.forName()和java.reject包里面的方法

  6.    虚拟机启动某个标注为启动类的类(mian方法)

问题:

1.因为实例化一个子类的时候会先执行父类的构造方法,所以是不是也相当于实例化了一个父类对象?

实例化对象的时候确实会执行一次构造方法,但是执行构造方法只是为了为变量赋值,并不能说实例化了对象。

2.加载后的类会放在哪里?

没有实例化的class会被ClassLoader在堆里面创建一个代表这个类的class对象作为访问方法区的入口。

原文地址:https://www.cnblogs.com/frank9571/p/12370944.html