java 类加载与静态块初始化

在这个类第一次被调用或实例化的时候就会被执行(因为此时类开始加载)。
静态代码块只会执行一次,一般会用来初始化一些值,并且在所有对象中全局共享。
静态变量,静态方法,静态代码块是在加载类的时候执行的,只发布到tomcat服务器上,但是并没有加载这个类,也不执行,访问这个类的时候才开始加载。
类加载是为了执行静态方法



在第一次创建一个类的对象或者第一次调用一个类的静态属性和方法的时候,会发生类加载

类加载期间,如果发现有静态属性,就给对应的静态属性分配内存空间,并赋值

这个过程完成之后,今后在调用该类的静态属性,虚拟机会直接寻找改属性先前已经分配的内存空间地址,然后调用其值。同样,修改这个类的静态属性也一样

说白了,静态属性将永远占用某一块固定的内存空间,知道程序终止
但是这里有点说不通,假如一个静态的字符串,运行过程中,不断修改这个字符串的值,那么其内存空间就不可能固定,所以可以认为这个静态字符串的引用是固定的

java 类初始化过程

对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是(静态变量、静态初始化块)>(变量、初始化块)>构造器

类加载到jvm需要经历如下几个过程:

一.加载
    通过类的全限定名转换为二进制字节流,在jvm堆中生成代表这个Class的对象,作为方法区域的方法入口.

二.连接
   1.验证:验证class的字节流是否对jvm虚拟机造成伤害,是否符合jvm的规范,这里包含几个验证.
   2.准备:为类的static变量赋初始值,其中不包含类其它实例成员的初始化.
   3.解析:将常量池内的符号引用替换成直接引用
三.初始化
    这里是static{}块,构造函数,代码块{}的执行过程.
四.使用
    对象的属性,方法等调用操作.
五.销毁
    jvm通过确定对象没有引用后进行gc操作.





JRE 的依需求加载究竟是在什么时候把类加载进入内部的呢?

我们在定义一个类实例的时候,比如 TestClassA testClassA ,这个时候 testClassA 的值为 null ,也就是说还没有初始化,没有调用 TestClassA 的构造函数,只有当执行 testClassA = new TestClassA() 以后, JRE 才正真把 TestClassA 加载进来。
1. JAVA类装载器在装载类的时候是按需加载的,只有当一个类要使用(使用new 关键字来实例化一个类)的时候,类加载器才会加载这个类并初始化。


     两种方法:
    |
    +-- 隐式的 : 使用new关键字让类加载器按需求载入所需的类
    |
    +-- 显式的 :
                     |
                     +-- 由 java.lang.Class的forName()方法加载
                     |
                     +-- 由 java.lang.ClassLoader的loadClass()方法加载

    (1) 使用Class.forName()
    Class.forName()方法具有两个重载的方法:
            +- public static Class forName(String className)
            |
            +- public static Class forName(String className, boolean initialize,ClassLoader loader)
    参数说明:
        className - 所需类的完全限定名
        initialize - 是否必须初始化类(静态代码块的初始化)
        loader - 用于加载类的类加载器
调用只有一个参数的forName()方法等效于 Class.forName(className, true, loader)。
这两个方法,最后都要连接到原生方法forName0(),其定义如下:
private static native Class forName0(String name, boolean initialize,ClassLoader loader) throws ClassNotFoundException;
只有一个参数的forName()方法,最后调用的是:
forName0(className, true, ClassLoader.getCallerClassLoader());
而三个参数的forName(),最后调用的是:
forName0(name, initialize, loader);
所以,不管使用的是new 來实例化某个类、或是使用只有一个参数的Class.forName()方法,内部都隐含了“载入类 + 运行静态代码块”的步骤。而使用具有三个参数的Class.forName()方法时,如果第二个参数为false,那么类加载器只会加载类,而不会初始化静态代码块,只有当实例化这个类的时候,静态代码块才会被初始化,静态代码块是在类第一次实例化的时候才初始化的。

你可能感兴趣的:(java 类加载与静态块初始化)