JAVA虚拟机类加载机制笔记

可在微信公众中查看该文章: http://mp.weixin.qq.com/s/qKR04b2aGBVdk30TsDZXdw

1、虚拟机的类加载机制:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的java类型;
2、在java语言中,类的加载、连接和初始化过程都是在程序运行期间完成的;缺点:令类加载时增加性能开销;优点:会为java应用程序提供高度的灵活性,可动态加载类和动态连接;
3、类加载生命周期:加载、验证、准备、解析、初始化、使用、卸载;验证、准备、解析这3个过程统称为连接;
4、触发初始化阶段:遇到new、getstatic、putstatic、invokestatic这4个指令时,需先触发类初始化;使用java.lang.reflect包中的方法对类进行反射时,也需要先触发类初始化;
初始化子类时,发现父类没有初始化,则先初始化父类;虚拟机启动时需指定一个要执行的主类(含main()方法的类),虚拟机会先初始化这个主类;接口在初始化时,不需要其父类立即初始化,只需在真正使用父接口时才初始化;
5、接口文件中不能使用静态代码块static{}
6、加载阶段(加载到内存的方法区进行储存):a)先通过一个类的全限定名来获取定义此类的二进制字节流(可以从zip、jar、ear、war、网络等中获取,也可以在反射运行中代理生成);b)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;c)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口;数组类本身不通过类加载器创建,它是由java虚拟机直接创建;
7、验证阶段:目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全,防止恶意代码的攻击;大致分为4个阶段的验证动作:文件格式验证、元数据验证、字节码验证、符号引用验证;
如果出现诸如java.lang.NoSuchFieldError、java.lang.NoSuchMethodError等异常,都是属于符号引用验证,符号引用验证的目的是保证解析阶段能正常执行。
8、准备阶段:是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将会在方法区中进行分配;此时进行内存分配的只有被static修饰的类变量,不包括实例变量,实例变量将会在对象实例化时随着对象一起分配到java堆中;
public static int value = 123,变量value在准备阶段过后的初始值为0,而不是123;准备阶段尚未开始执行任何java方法
public static final int value = 123,变量在准备阶段过后的值为123
9、解析阶段:此阶段是虚拟机将常量池内的符号引用替换为直接引用的过程;
符号引用:以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地订位到目标即可;
直接引用:可以是直接执行目标的指针、相对偏移量或是一个能间接定位到目标的句柄;
符号引用于虚拟机实现的内存布局无关,而直接引用是相关的;
解析动作包含:类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定解析等7种解析;
10、初始化阶段:此阶段是执行类构造器<clinit>()方法(不是构造函数)的过程;<clinit>()方法是有编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{})中的语句合并产生的,编译器收集的顺序是有语句在源文件中出现的顺序决定的,静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但不能访问。
子类构造器方法执行之前,父类的构造器方法已经执行完毕;接口中不能使用静态代码块,执行接口的构造器方法之前,不需要先执行父类的构造器方法;只有在子接口中调用父接口的变量时,父接口才会初始化;
虚拟机会保证一个类的构造器<clinit>()方法在多线程环境中被正确地加锁、同步。如果多个线程同时去初始化一个类,那么只有一个线程去执行这个类的<clinit>()方法,其他线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕,会唤醒其他阻塞的线程,但是这个阻塞的线程不会再次执行<clinit>()方法,因为同一个类加载器下,一个类型只会初始化一次。
11、类加载器:类加载阶段中“通过一个类的全限定名来获取定义此类的二进制字节流”这个动作放在java虚拟机外部去实现,以便让应用程序决定如何去获取所需要的类,实现这个动作的代码模块就是“类加载器”;
12、比较两个类是否相等,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载他们的类加载器不同,那这两个类就必定不相等。
13、3种类加载器:启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用程序类加载器(Application ClassLoader)
14、双亲委派模型的工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一层次的类加载器都是如此,因此所有的加载请求都会传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己加载。

猜你喜欢

转载自itxiaojiang.iteye.com/blog/2376769