此处主要需要知道什么是java虚拟机?java虚拟机如何进行类加载的?
java语言本身是编译型和解释型的语言,先对本地的java文件进行编译,编译后会在本地生成一个class文件,而这个生成的class文件就是java虚拟机需要加载的类
所谓的java虚拟机就是JVM(java virtual machine),对应不同的操作系统有不同的版本,如有window版本,Linux版本等,正是因为JVM,java语言才实现了跨平台。
而编译和解释分开,可以实现一次编译,处处运行,只需要加载class类到内存中,即可实现运行,而无需从新编译。若文件修改了,会重新进行编译。
虚拟机的类加载机制:把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的java类型
在java语言里,类的加载,连接和初始化都是在运行期间完成的,这种策略会降低性能,但提供了灵活性,java的动态扩展功能就是依赖于运行期间的动态加载和动态连接来实现的。
使用java运行期间类加载的实例:
1.编写的接口应用程序,可以等到运行时在指定其实现类;
2.用户自定义的类加载器,可以让本地程序在运行时从网络上下载一段二进制流数据作为程序代码的一部分。
类的生命周期:
加载,验证,准备,初始化和卸载的顺序是确定的,类的加载必须按照这个顺序开始(不是运行,可以交叉进行),而解析阶段则不一定,它在某些情况下可以在初始化之后再开始,为支持java的动态绑定。
类加载的过程:
加载,验证,准备,解析,初始化几个阶段的具体操作
加载:是类加载过程中的一个阶段,
1)通过类的全限定名获取此文件的二进制字节流,
2)将字节流所代表的静态存储结构转换为方法区的运行时数据结构
3)在内存中生存一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
对于Hotspot虚拟机而言,Class对象比较特殊,它虽然是对象,但是存放在方法区里面。
验证:验证是连接阶段的第一步,为了保证Class文件中的字节流中包含的信息是符合虚拟机的要求的,不对虚拟机有危害。这个阶段很重要,决定了虚拟机是否能承受恶意的攻击。
大致完成4个校验:文件格式验证(字节流是否符合规范),元数据验证(对字节码语义解析,其信息符合java规范要求),字节码验证(语义合法,符合逻辑),符号引用验证(符号引用转为直接引用)。
准备:正式为类变量分配内存并设置类变量初始化值,都在方法区中进行分配。分配的是static修饰的变量,初始化值一般为默认值,
解析:是虚拟机将常量池内的符号引用替换为直接引用的过程,
1)符号引用:以一组符号来描述所引用的目标,只要符号在使用时可以直接定位到目标即可。
如:String st1="java"; String st2=" programm" ; String st3=st1+st2; 这是属于符合引用,在解析时,会把String st3=st1+st2 替换为st3="java programm",
2) 直接引用:直接引用可以直接指向目标的指针,相对偏移量或者一个能间接定位到目标的句柄。如果有了直接引用,则引用的目标已经在内存中存在。
初始化:类初始化阶段是类加载的最后一步,在此阶段,才开始真正的执行java程序代码(字节码)。
初始化阶段是执行类构造器<clinit>()方法的过程。clinit()方法对类或者接口来说并不是必须的,如果一个类中没有静态语句块,也没有对变量的赋值操作,则编译器也可以不为这个类生成clinit方法。
一般java程序中运行程序需要程序规定的public static void main(String []args){}这个方法作为入口,符合初始化的要求,main是静态方法,这样类在初始化时会执行此方法。