合肥seo建站,十六局门户网登录,北京公司建设网站,网站需要网监备案导航一、过程概述二、Loading2.1 类加载器2.2 双亲委派机制2.3 类在内存中的结构三、Linking四、Initializing一、过程概述
java 源文件编译后会生成一个 .class文件存储在硬盘上。
在程序运行时#xff0c;会将用到的类文件加载到 JVM 内存中。从磁盘到内存的过程总共分为三…
导航一、过程概述二、Loading2.1 类加载器2.2 双亲委派机制2.3 类在内存中的结构三、Linking四、Initializing一、过程概述
java 源文件编译后会生成一个 .class文件存储在硬盘上。
在程序运行时会将用到的类文件加载到 JVM 内存中。从磁盘到内存的过程总共分为三个步骤加载、连接、初始化。 LoadingLinkingInitializing 二、Loading
Loading 过程是把一个 class 文件加载到内存中去。
2.1 类加载器
JVM 加载类的方式是按需动态加载采用双亲委派机制。
认识几种系统提供的类加载器 Bootstrap 启动类加载器负责加载指定目录——JAVA_HOME/lib下的 rt.jar、charset.jar 等核心类库由 C实现是JVM 的不可分割的一部分。类加载范围可以在 Launcher 类中查看 ExtClassLoader 扩展类加载器负责加载指定目录——JAVA_HOME/lib/ext 下的扩展包或者也可以由 -Djava.ext.dirs 参数指定。类加载范围可以在 Launcher 类中查看 AppClassLoader 应用类加载器加载用户应用的 classpath 下的 class 文件这是应用程序的默认类加载器用户自定义的类都是通过这个类加载器来加载。类加载范围可以在 Launcher 中查看 自定义类加载器开发者自定义的 ClassLoader继承自 ClassLoader 抽象类并重写 findClass(…) 。
类加载器除 C实现的 Bootstrap 外本身就是一个普通的 classJVM 所有的 class 都是被类加载器加载到内存的。
public class TestLoadClass {public static void main(String[] args) {System.out.println(TestLoadClass.class.getClassLoader());System.out.println(TestLoadClass.class.getClassLoader().getParent());// Bootstrap 由 C 实现Java 中没有具体的类与之对应故返回 nullSystem.out.println(TestLoadClass.class.getClassLoader().getParent().getParent());}
}output:
sun.misc.Launcher$AppClassLoader58644d46
sun.misc.Launcher$ExtClassLoader4554617c
null2.2 双亲委派机制
JVM 加载类时处于安全考虑基础类和扩展类等都必须由指定的类加载器来加载不同的类加载器有自己的命名空间同一个类如果由不同的类加载器加载会在内存中存在多份类对象。也正因如此JVM 的类加载机制要求诸如 java.lang.Object 这种基础类必须由最基础的 Bootstrap 来加载。
因此整个 Loading 的过程就成了底层类加载器收到类加载请求后必须将请求层层传递给父级加载器检查确认是否应该由父级加载器加载若由于父加载器的指定类路径中没有该类文件就会再层层向下返回最终才会去加载 Tip注意AppClassLoader 的父加载器是 ExtClassLoaderExtClassLoader的父加载器是Bootstrap 加载器。 这里的父加载器并不是 Java 多态中语法的 extends 继承关系而是一种架构上的层级关系AppClassLoader 和 ExtClassLoader 之间没有任何继承关系它们在语法上都继承自 ClassLoader 抽象类实际上 ClassLoader 中维护了一个 ClassLoader parent 引用这才是 “双亲” 的真实面目即 AppClassLoader 的父加载器实际上是其内部的一个组合对象。 2.3 类在内存中的结构
加载的时候创建了两块内容第一块内容是把 Xxx.class 二进制扔到内存中第二块内容是生成一个 Class 类的对象该对象中的变量会指向前一块的实际内存地址这一步实际上是Resolution 的过程。
三、Linking
Linking连接这是一个大的步骤其中又分为三个小步骤 Verification 验证Preparation 准备Resolution 解析 验证校验 class 文件格式是否符合 jvm 规范如开头的魔数等。 准备将 class 中的静态变量赋默认值所谓默认值举个例子int 类型默认值是 0String 类型默认值是 null。 解析把class 文件常量池中的符号引用转化为直接内存地址。
四、Initializing
初始化区别于 Linking 中的 Preparation 此过程将静态变量赋初始值。比如
public static int num 8;这个 num 静态变量会在 Preparation 阶段赋值 0 在 Initializing 阶段赋值 8。
Java初始化的时机JVM规范中有明确规定自然加载也一定是在初始化之前完成。JVM规范中定义了以下这些必须初始化完毕的场景
new读取和设置 static 变量只触发直属类的初始化例如子类直接引用父类中的 static 变量只初始化父类调用 static 方法子类初始化之前父类必须完成初始化main 函数所在的类在执行之前必须完成初始化通过反射获取类信息 注意对于 static final 类型的属性在编译之后即存储在字节码文件的常量池中直接引用它不会触发初始化。 记忆技巧
new 是创建对象而对象的创建一定需要类信息的支持static 变量和方法又称为类变量、类方法它们都需要类指针来访问。main也属于static 方法子类是父类的扩展子类都要初始化了父类当然一定要先初始化反射是使用类信息的一种技术当然需要先初始化类