JVM 1.类的加载、连接、初始化

Java类的加载是由类加载器来完成的,过程如下:

首先,加载是把硬盘、网络、数据库等的class文件中的二进制数据加载到内存的过程,然后会在Java虚拟机的运行时数据区的堆区创建一个Class对象,用来描述该类,再在方法区存放这些二进制数据,用来保存类对应的数据结构

Java的类加载器有哪些?

下面的String对象是由bootstrap根类加载器加载的,而自定义类C是由系统加载器加载的:

/**
 * 源文档中这样描述:
 *     Some implementations may use null to represent the bootstrap class loader. 
 *         This method will return null in such implementations 
 *         if this class was loaded by the bootstrap class loader.
 * @author Administrator
 *
 */
public class ClassLoader2 {

    //测试
    public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Class.forName("java.lang.String");
        System.out.println("String类的加载器:"+c1.getClassLoader());//bootstrap根类加载器(C++实现的),返回null
        Class c2 = Class.forName("com.mlxs.classloader.MyClass");
        System.out.println("自定义MyClass类的加载器:"+c2.getClassLoader());//AppClassLoader 系统(应用)加载器
        /**
         * 返回数据:
         *     String类的加载器:null
         *    自定义MyClass类的加载器:sun.misc.Launcher$AppClassLoader@425224ee
         */
    }

}

class MyClass{
    
}

关于初始化,什么情况下初始化类?在主动使用的时候初始化:

一个例子:

public class ClassLoader1 {

    private static ClassLoader1 classLoader1 = new ClassLoader1();
    private ClassLoader1(){
        a ++;
        b ++;
    }
    public static int a;
    public static int b = 0;
    public static ClassLoader1 getIntsance(){
        return classLoader1;
    }
    
    //测试
    public static void main(String[] args) {
        ClassLoader1 clazz = ClassLoader1.getIntsance();
        /**
         * 类加载后,
         *     准备阶段:(1)classLoader1赋值null,(2)a和b都赋值默认值0;
         *  初始化阶段: (1)new classLoader1的时候,a++(=1),b++(=1)
         *            (2)a没默认值,值不变;b默认值为0,b赋值0
         * 所以,最后a=1,b=0
         * 
         * 如果把new ClassLoader1()放到int a b 的后面,则最后a=1,b=1
         */
        System.out.println("a:"+clazz.a);
        System.out.println("b:"+clazz.b);
    }

}

结果:

a:1
b:0

  

要注意的是:

子类主动使用,会导致父类的初始化;而父类主动使用,不会使子类初始化。如,new Object() 不会导致它的子类(所有的Java类)都初始化

而子类实现接口,当子类被初始化,不会导致接口初始化。只有当接口中的静态变量被使用时才会初始化

逃避不一定躲得过,面对不一定最难过
原文地址:https://www.cnblogs.com/yangzhenlong/p/5172438.html