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类)都初始化
而子类实现接口,当子类被初始化,不会导致接口初始化。只有当接口中的静态变量被使用时才会初始化
逃避不一定躲得过,面对不一定最难过