Java类加载基本过程
-
根据类的全限定名称加载定义类的二进制字节流。
-
将字节流代表的静态存储结构转化为方法区的运行时数据结构
-
内存中生成一个代表这个类的java.lang.Class对象,作为方法去这个类的各种数据访问入口
-
0xCAFEBABY 魔数开头;
-
主次版本号当前虚拟机可处理;
-
常量类型;
-
索引执行类型;
-
utf8编码数据类型,
-
是否有父类;
-
父类是否继承了final修饰的类;
-
非抽型类是否实现了父类或接口中需要实现的方法;
-
类中的字段、方法的覆盖,重载矛盾;
-
符号引用中通过字符描述的全限定名是否能找到对应的类;
-
指定类中是否存在符合方法字段的描述符,及简单名称所描述的方法和字段;
-
符号引用中类,字段,方法的访问性。
-
初始值通常为数据类型的零值,final修饰的值直接初始化为相应值。
-
类变量为static修饰的变量,区分于实例变量。
-
符号引用:以一组符号来描述所引用的目标,任何形式的字面量,只要使用时能无歧义的定位到目标,,与虚拟机内存实现无关,无关引用目标是否加载。
-
直接引用:直接指向目标的指针,偏移量或间接定位到目标的句柄,和虚拟机实现的内存相关,直接引用相关的目标对象必须已加载。
-
。。。
-
编译器根据类文件中定义顺序自动收集类中的类变量的赋值动作和静态语句块儿的语句合并产生,静态语句块儿只能访问到其前定义的变量。
-
区别于类的构造方法,不需要显示的调用父类构造器,虚拟机保证子类的<cinit>()执行之前父类的<cinit>()已经执行完成。
-
父类中的静态语句块儿执行于前。
-
<cinit>()对于类或接口不是必须的,如果没有变量赋值操作或静态语句块儿,则不生成。
-
接口的<cinit>()不需要先执行父接口的<cinit>(),同样接口的实现类<cinit>()也不需要。
-
线程安全:虚拟机保证多线程环境中<cinit>()正确的加锁,同步,同一时间只能有一个线程访问初始化类的<cinit>()