网站首页 > java教程 正文
在Java中类的加载过程是Java虚拟机将类的字节码加载到内存中、进行验证、然后解析和初始化的过程。在这个过程中涉及多个步骤和执行阶段。Java的类加载机制是动态的,即类在运行时才会被加载。这种机制为Java的高灵活性和跨平台特性提供了支持。下面我们就来详细的介绍一下相关的内容。
类加载器 (Class Loader)
Java提供了三种主要的类加载器来动态加载类,如下所示。
- Bootstrap ClassLoader(引导类加载器):负责加载JVM核心类库,例如rt.jar中的类(如java.lang.*等)。它是由C/C++代码实现的,处于JVM内部。
- Extension ClassLoader(扩展类加载器): 负责加载Java扩展库,例如$JAVA_HOME/lib/ext/目录中的类。
- Application ClassLoader(应用类加载器): 负责加载应用程序的类路径CLASSPATH中的类。
Java的类加载器遵循双亲委托机制,即当一个类加载器尝试加载类时,它首先将请求委托给父类加载器,如果父类加载器无法加载该类,才由当前类加载器进行加载。
类加载的生命周期
类的加载生命周期主要包括以下五个阶段
加载(Loading)
类的字节码文件(.class文件)通过类加载器从文件系统、网络或者其他来源加载到内存中。在此过程中,JVM会为每一个加载的类在方法区(Method Area)中生成一个Class对象,它封装了该类的信息,例如类的名称、父类、实现的接口、字段、方法等。
链接(Linking)
链接过程由三个小步骤组成
- 验证(Verification): 验证加载的字节码是否符合JVM的规范,以确保字节码不会破坏JVM的安全性。例如,确保类文件格式合法,数据类型符合规范,父类和子类的兼容性等。
- 准备(Preparation): 为类的静态字段分配内存并初始化为默认值。例如,如果有static int x,那么会为x分配内存并赋值为默认值0。
- 解析(Resolution): 将类、字段、方法的符号引用(符号化的名称)解析为直接引用(内存地址)。符号引用指的是类文件中的抽象符号,而直接引用是类加载器所生成的可以被直接使用的实体。
初始化(Initialization)
初始化阶段是执行类构造器方法的过程。类构造器是由编译器自动生成的,用于初始化类的静态变量和执行静态代码块。如果类存在静态字段,或者有静态代码块,它们会在此阶段执行,并对字段赋初始值。初始化方法只执行一次,是线程安全的。
使用(Using)
当类被加载并初始化后,它的实例可以被创建,类的静态方法可以被调用,静态字段可以被访问。
卸载(Unloading)
类的卸载是由垃圾回收器负责的。当某个类的Class对象不再被引用时,并且这个类的所有实例都被回收,JVM会在适当的时候卸载这个类。类的卸载是无法强制触发的,通常由JVM自动进行。
类加载器的双亲委托模型
Java的类加载器使用了父委托机制,即当一个类加载器收到类加载请求时,它会首先将该请求委托给父加载器处理。父类加载器处理的顺序是从最顶层的Bootstrap ClassLoader开始,依次向下。只有当父类加载器无法找到类时,才会由当前类加载器进行加载。
双亲委托机制的优势
- 避免类的重复加载: 如果某个类已经被父类加载器加载,那么子类加载器不需要再次加载。
- 保证核心类库的安全性: 由于核心类库由引导类加载器加载,应用程序无法伪造和替换核心类库中的类。
虽然Java类加载器遵循父委托模型,但在一些情况下,开发者可能会打破这种机制,通常通过创建自定义类加载器,继承自ClassLoader类并覆盖loadClass()方法。这种做法在一些框架,例如OSGi、Tomcat等中比较常见,它们通过定制类加载器来隔离不同的类加载上下文。
类的主动引用与被动引用
类的加载有两种类型,如下所示。
主动引用
主动引用会导致类的加载和初始化,包括以下情况:
- 使用new关键字创建类的实例。
- 调用类的静态方法或者访问类的静态变量。
- 使用反射来访问类。
- 初始化某个类的子类时,会先初始化父类。
- JVM启动时指定的主类。
被动引用
某些情况不会触发类的初始化,即不会调用初始化方法方法:
- 通过子类访问父类的静态字段,只会初始化父类,而不会初始化子类。
- 定义数组时不会初始化数组元素的类,例如MyClass[] array = new MyClass[10];不会初始化MyClass。
- 访问final常量(编译期常量),因为这些常量在编译期已被嵌入调用类的常量池中。
总结
Java的类加载过程是一个复杂而关键的过程,包含了加载、链接、初始化等多个阶段,并依赖于类加载器及其父委托模型来确保类的唯一性和安全性。理解类加载机制有助于开发者在处理类加载异常、ClassNotFoundException、NoClassDefFoundError等问题时更好地进行调试和解决问题。
猜你喜欢
- 2025-02-04 SpringBoot开发 - 什么是热部署和热加载?devtool的原理是什么?
- 2025-02-04 JVM详解之:类的加载链接和初始化(类加载java)
- 2025-02-04 面试官:什么是java类加载当中的双亲委派?
- 2025-02-04 jvm超详细探索自定义类加载器(值得收藏)
- 2025-02-04 详解java反射的原理(java 的反射)
- 2025-02-04 JVM性能调优(1)——JVM内存模型和类加载运行机制
- 2025-02-04 Java反射:作用与原理解析(java反射到底有什么用)
- 2025-02-04 java类加载与初始化(java类的加载机制及加载过程)
- 2025-02-04 类加载的验证阶段你不知道的东西(类加载检查)
- 2025-02-04 类是如何加载的?(类的加载过程是什么?简单描述一下每个步骤)
你 发表评论:
欢迎- 最近发表
-
- Java常量定义防暴指南:从"杀马特"到"高富帅"的华丽转身
- Java接口设计原则与实践:优雅编程的艺术
- java 包管理、访问修饰符、static/final关键字
- Java工程师的代码规范与最佳实践:优雅代码的艺术
- 编写一个java程序(编写一个Java程序计算并输出1到n的阶乘)
- Mycat的搭建以及配置与启动(mycat部署)
- Weblogic 安装 -“不是有效的 JDK Java 主目录”解决办法
- SpringBoot打包部署解析:jar包的生成和结构
- 《Servlet》第05节:创建第一个Servlet程序(HelloSevlet)
- 你认为最简单的单例模式,东西还挺多
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)