JVM生命周期(1)-类的加载
JVM生命周期分成五个阶段:加载、连接(验证、准备、解析)、初始化、使用、卸载。
一、类的加载:
最常见,将已存在的字节码文件(class文件)从磁盘中读取加载到内存里面,也可以从网络中读取的class文件加载到内存里面。将其放到运行时数据区的方法区中,然后在内存中创建一个Class对象用来封装类在方法区内的数据结构。(规范并未说明Class对象放置于何处,具体实现要看JVM厂商,Hotspot虚拟机是将其放于方法区内)Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。
因此类的加载最终产品:位于内存中的 Class对象。
一个类不管创建多少的实例,它的Class对象只有唯一的一份。(注意前提:类加载器位于同一个命名空间之下)
类的加载器就是加载类的工具。每个类加载器都有自己的命名空间,命名空间是由该加载器及所有父类加载器所加载的类组成。
在同一个命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类。
在不同命名空间中,有可能会出现类的完整名字(包括类的包名)相同的两个类。
二、类加载器
类加载器分成两种:Java自带的类加载器、用户自定义的类加载器。
1、自带的类加载器:
根加载器(BootstrapClassLoader)
扩展类加载器(ExtClassLoader)
系统类加载器(AppClassLoader)
2、自定义类加载器
继承java.lang.ClassLoader的子类都是自定义类加载器。只需要重写ClassLoader.findClass(name)方法即可。不推荐使用重写loadClass(name)方法。
类加载器最上级根加载器是由C++实现,它的父加载器为null。类加载器关系组成是树状结构,但实际上更多是一种包含关系。类加载使用了一种双亲委托机制来处理加载顺序问题。
双亲委托:当加载一个类时,并不会马上实行,而是委托给父类进行加载,父类也同样进行操作判断,直至搜寻到最后的父类为null时,即根加载器,再往下逐级加载,加载成功则返回。
最优先根类加载,根类加载不到,让扩展类加载,再让系统类加载,当所以都 加载不成功时抛出异常。
除了根加载器外,其余加载器有且只有一个父类加载器。
三、ClassLoader
每个类对象都 包含对定义它的类加载器的引用。
数组类的class对象并不是类加载器创建的,JVM根据需要自动创建的。
数组类的加载器与数组元素的加载器相同,如果元素类型为原始类型,数组元素是没有类加载器。
classLoader使用委托模型进行搜索类和资源,每个ClassLoader的实例都会有一个关联的父类加载器。虚拟机内建的加载器称为根类加载器或启动类加载器。
四、加载字节码(class)文件的方式
1、从本地系统直接加载
2、通过网络下载.class文件加载
3、从zip,jar等归档文件中加载.class文件
4、从专有数据库中提取.class文件加载
5、将Java源文件动态编译成.class文件加载 (动态代理)