文章目录
- 类加载机制
- 类加载器
- 类加载器分类
- 类加载步骤
- 1.加载(Loading)
- 2.连接(Linking)
- 3.初始化(init)
- 变量初始化步骤
- 双亲委派机制
类加载机制
类加载器
类加载器是将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构。
类加载器分类
- 启动类加载器:也叫根加载器,是虚拟机自带的加载器,用于加载Java基础类库,包含Java运行环境所需的基础类。
- 拓展类加载器:虚拟机自带的加载器,由Java语言实现,用于加载$JAVA_HOME/jre/lib/ext/.jar目录下的class文件。
- 应用程序类加载器(AppClassLoader):虚拟机自带的加载器,用于加载当前应用的classpath的所有类,也就是我们自己写的那些Java代码。
- 用户自定义加载器:通过继承Java.lang.ClassLoader抽象类自定义一个类加载器。
类加载步骤
1.加载(Loading)
通过一个类的全类名获取其二进制字节流,将这个二进制流代表的静态存储结构转化为方法区的运行时数据结构,然后在内存中生成一个代表这个类的java.lang.Class对象,作为方法区中这个类的各种数据的访问入口。
2.连接(Linking)
该过程又可以分为三个阶段:验证Verfication,准备Preparation和解析Resolution)。
- 验证阶段 用于确保加载的Class文件的字节流包含的信息是否符合虚拟机要求,保证其正确性合法性;
- 准备阶段 为类变量(static修饰的变量)分配内存并根据对象类型设置相应的默认初始值(比如int
类型为0,Integer类型为null)。 - 解析阶段 用于将符号引用转换为直接引用。
3.初始化(init)
该阶段就是执行类的构造器方法()的过程 。
clinit不是类的构造器,不需要我们自己定义,是javac编译器自动搜集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。
一个类不包含类变量(静态变量)和静态代码块,那么它的字节码中就不会有构造器方法()。
变量初始化步骤
- 静态变量 (类变量)在类加载过程的初始化阶段才会被赋值。
- 常量在编译的时候就会被分配具体值。
- 成员变量 在对象初始化时赋值。
双亲委派机制
所谓的 双亲委派机制 就是:当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此。只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。
优点:
采用双亲委派的一个好处是:不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个String对象,所以我们自定义的Java类并不会污染JDK自带的那些类(即使全类名一样),这种保护机制也叫沙箱安全机制。