类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定标识(以CA FE BA BE标识符开头)。
ClassLoader只负责加载class文件,是否可以运行由执行引擎ExecutionEngine决定。
加载类的信息放到方法区的内存空间。除了类信息,方法区还会存放常量池信息,可能还包括字符串字面量和数字常量(class文件中常量池部分的内存映射)
加载阶段loading
通过一个类的全类名获取二进制字节流,将字节流所代表的的静态存储接口转化为方法区的运行时数据结构,在java内存中生存一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。将class文件进行加密可防止被反编译
链接阶段linking
验证verify:目的是为了确认class文件符合虚拟机要求,防止危害自身。主要包括:文件格式、元数据、字节码、符号等的验证
准备prepare:为类变量分配内存并设置默认值,不包括final修饰的类变量,因为final在编译阶段就已经分配了。分配到方法区中
解析resolve:将常量池内的符号引用转为直接引用,事实上解析操作会在初始化完成之后再执行。
初始化阶段initialization
执行类构造器方法clinit()的过程,此方法是javac编译器自动收集类中的所有类变量的赋值动作和静态代码中的语句合并而来。指令按源文件中的顺序执行。如有父类,先执行父类的clinit()方法
补充:
类加载器分类:引导类加载器BootStrap ClassLoader 和自定义加载器(扩展类加载器、系统各类加载器、用户自定义的加载器)
Java核心库由引导类加载器加载,自定义的类和第三方的类库一般都是由系统类加载器加载
什么时候需要用户自定义类的加载器?
隔离加载类、修改类的加载方式、扩展加载源、防止源码泄露
什么是双亲委派机制?
虚拟机对class文件采用按需加载,在加载时采用双亲委派模式,把请求交给父类处理。什么样的类该由哪个类加载器去加载,是在类加载器中有明确定义的。当我们自己定义的类(java\lang\String.class)由引导类加载器加载时,会触发沙箱安全机制,保护源码安全。