java面试题-JVM类加载机制

article/2025/9/22 4:02:34
  1. 类加载的生命周期?

1. 加载阶段(Loading)

在Java程序中,当需要使用某个类时,JVM会使用类加载器来查找并加载该类文件。类加载器会首先从文件系统或网络中查找相应的 .class 文件,读取类的二进制数据,并将其存储在JVM的内存中。在这个过程中,JVM会为该类创建一个对应的Java类对象。这个Java类对象包含了该类的类名、父类名、接口名、访问修饰符、成员变量和成员方法等信息。

2. 链接阶段(Linking)

在类加载完成后,JVM会对该类进行链接。链接分为三个步骤:验证、准备和解析。

  • 验证阶段:在验证阶段,JVM会对类文件的格式、依赖关系、语义等进行检查。如果验证失败,JVM会抛出相应的异常。

  • 准备阶段:在准备阶段,JVM会为类的静态成员分配内存空间,并设置默认初始值。在Java程序中,静态变量的默认初始值是0或null,而不是程序员在代码中定义的初始值。如果类的静态成员是常量,则在编译期间就已经分配了内存空间,并设置了正确的初始值。因此,在准备阶段,常量并不需要分配内存空间。

  • 解析阶段:在解析阶段,JVM会将类中的符号引用转换为直接引用。在Java程序中,类中的方法调用、变量引用等都是通过符号引用实现的。而在JVM中,这些符号引用需要被解析为直接引用,以便JVM能够正确地执行程序。在解析阶段,JVM会将符号引用转换为直接引用,并生成相应的调用指令。

3. 初始化阶段(Initialization)

在初始化阶段,JVM会为类的静态成员赋予正确的值。在Java程序中,静态变量和静态代码块的初始化操作都是在初始化阶段完成的。当JVM完成初始化操作后,Java程序才能正常地使用该类。需要注意的是,初始化操作只会执行一次。如果类已经被初始化过,JVM不会再次执行初始化操作。

总体来说,Java类加载器的生命周期可以分为加载、链接和初始化三个阶段。在这三个阶段中,JVM会对类文件进行验证、解析、分配内存空间、设置初始值等操作,以确保Java程序的正确执行。

2.类加载器的层次?

在Java中,类加载器的层次结构可以分为以下三个层次:

  1. 启动类加载器(Bootstrap ClassLoader)

启动类加载器是JVM内置的类加载器,它负责加载JRE核心库中的类,包括 rt.jarresources.jar 中的类。它是Java类加载器中唯一没有父类加载器的加载器,由JVM自身实现。在Java程序中,我们无法直接获取到启动类加载器的引用。

  1. 扩展类加载器(Extension ClassLoader)

扩展类加载器是用来加载JRE扩展目录中的类,通常位于 jre/lib/ext 目录下。它的父类加载器是启动类加载器。扩展类加载器的实现由JVM提供,它可以通过 java.lang.ClassLoader.getSystemClassLoader().getParent() 获取到其父类加载器。

  1. 应用程序类加载器(Application ClassLoader)

应用程序类加载器(也称为系统类加载器)是用来加载应用程序类路径上的类,通常位于 classpath 下的类和库。它的父类加载器是扩展类加载器。应用程序类加载器的实现也由JVM提供,可以通过 java.lang.ClassLoader.getSystemClassLoader() 获取到其引用。

  1. 自定义类加载器

除了这三个基本的类加载器,Java还支持自定义类加载器。自定义类加载器可以继承自 java.lang.ClassLoader 类,通过重写其中的 findClass() 方法和 loadClass() 方法实现类的加载。这样可以实现特定的类加载需求,比如从网络或数据库中动态加载类。在实现自定义类加载器时,需要注意遵循双亲委派模型的原则,保证类的唯一性和正确性。

3.Class.forName()和ClassLoader.loadClass()区别?

在Java中,Class.forName()ClassLoader.loadClass() 都可以用来加载类,但二者有一些区别。

  1. 类加载器的区别

Class.forName() 方法使用的是当前线程的类加载器(即调用 Class.forName() 方法的类的类加载器)来加载指定的类。如果没有指定类加载器,那么默认使用的是系统类加载器。如果这个类还没有被加载,那么该方法将加载并初始化这个类。如果这个类已经被加载,那么该方法将返回这个类的 Class 对象。此外,Class.forName() 还可以指定是否要初始化这个类。

ClassLoader.loadClass() 方法是一个实例方法,需要通过类加载器的实例来调用。它只是简单地加载指定的类,但不会对其进行初始化操作。如果想对这个类进行初始化,需要调用 Class.forName()Class.newInstance() 方法。

  1. 返回值的不同

Class.forName() 方法返回一个 Class 对象,该对象包含了类的所有信息,包括类的名称、方法、属性等。

ClassLoader.loadClass() 方法只是简单地加载类,返回的是一个 Class<?> 类型的对象,只包含类的类型信息。如果需要使用该类的实例对象,还需要通过反射或者其他方式来获取。

  1. 加载类的方式的不同

Class.forName() 方法会在加载类的同时对其进行初始化操作,这意味着会执行静态代码块和初始化类变量等操作。

ClassLoader.loadClass() 方法只会简单地加载类,不会执行任何初始化操作。如果需要对类进行初始化,需要手动调用 Class.forName() 或者 Class.newInstance() 方法。

需要注意的是,Class.forName()ClassLoader.loadClass() 在加载类时都会遵循双亲委派模型。即当一个类加载器需要加载一个类时,它首先委派给其父类加载器去加载,如果父类加载器无法加载该类,再由该类加载器自己尝试加载。这样可以保证类的唯一性和正确性。

4.JVM有哪些类加载机制?

Java虚拟机(JVM)的类加载机制主要包括以下几种:

  1. 全盘负责机制(Bootstrap ClassLoader)

Java虚拟机内置的启动类加载器(Bootstrap ClassLoader)会负责加载Java平台核心库中的类,包括 java.langjava.util 等类。由于这些类都是由JVM实现的,因此在加载这些类时,不需要考虑类的版本和安全性问题。

  1. 父类委托机制(Parent Delegation Model)

父类委托机制是Java类加载机制中的核心机制。当一个类需要被加载时,它会先委托给父类加载器去尝试加载。如果父类加载器无法加载这个类,那么它才会由当前类加载器自己去加载。这个过程会一直持续到最顶层的启动类加载器为止,如果仍然无法加载该类,那么就会抛出 ClassNotFoundException 异常。

父类委托机制可以保证Java虚拟机中的类不会出现重名的情况,而且可以保证Java类库的安全性。

  1. 缓存机制(Cache Mechanism)

缓存机制是指,在类加载器加载一个类之后,会将这个类的Class对象缓存起来,下次再加载这个类时,就可以直接从缓存中取出,避免重复加载。

缓存机制可以提高类的加载效率,避免重复加载类的字节码,但同时也可能会导致内存泄漏问题。

  1. 双亲委派机制(Double-Delegation Mechanism)

双亲委派机制是一种更加严格的父类委托机制。在双亲委派机制中,除了顶层的启动类加载器,每个类加载器都有且只有一个父类加载器,并且会优先委托给父类加载器去加载类。如果父类加载器无法加载该类,才会尝试自己去加载。这样可以保证类的唯一性和正确性,避免了重复加载和安全问题。

  • 当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。

  • 当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。

  • 如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;

  • 若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException


http://chatgpt.dhexx.cn/article/iFEl3lrr.shtml

相关文章

JVM面试 类加载机制

JVM的类加载机制 一、JVM的运行机制 JVM 是用于运行Java字节码的虚拟机&#xff0c;包括一套字节码指令集&#xff0c;一组程序寄存器&#xff0c;一个虚拟机栈&#xff0c;一个虚拟机堆&#xff0c;一个方法区和一个垃圾回收器。JVM运行在操作系统之上&#xff0c;不与硬件设…

JVM--详解类加载机制

JVM--详解类加载机制 转载&#xff1a;https://blog.csdn.net/championhengyi/article/details/78680700 Java虚拟机的体系结构 前面我们探讨了Class文件的结构&#xff0c;如果你还没有学习&#xff0c;将不利于这部分知识的吸收与掌握&#xff0c;所以请移步&#xff1a;JV…

JVM类加载机制

文章目录 概述1. 类加载器2.类加载过程3.双亲委派机制总结 概述 Class文件由类装载器装载后&#xff0c;在JVM中将形成一份描述Class结构的元信息对象&#xff0c;通过该元信息对象可以获知Class的结构信息&#xff1a;如构造函数&#xff0c;属性和方法等&#xff0c;Java允许…

JVM:类加载机制

类加载器 什么是类加载器 ​ 类加载器的作用负责从磁盘中或者网络中加载class文件&#xff0c;classloader只负责加载class文件&#xff0c;类加载器通过一个类的全限定名来获取描述此类的二进制字节流。类加载器虽然用于实现加载动作&#xff0c;但它在Java程序中起到的作用…

JVM类的加载机制

1 类的加载机制 类的加载指的是将类的.class文件中的二进制数据读入到内存中&#xff0c;将其放在运行时数据区的方法区内&#xff0c;然后在堆区创建一个java.lang.Class对象&#xff0c;用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象&#xf…

jvm之java类加载机制和类加载器(ClassLoader)的详解

手把手写代码&#xff1a;三小时急速入门springboot—企业级微博项目实战--->csdn学院 当程序主动使用某个类时&#xff0c;如果该类还未被加载到内存中&#xff0c;则JVM会通过加载、连接、初始化3个步骤来对该类进行初始化。如果没有意外&#xff0c;JVM将会连续完成3个步…

二叉树的遍历

遍历一棵二叉树有很多种方法。假如用D、L、R分别代表二叉树的根结点、左子树、右子树&#xff0c;那么要遍历这棵二叉树&#xff0c;方法就有6种&#xff1a;DLR、DRL、LDR、LRD、RDL、RLD。一般在遍历时遵循先左后右的原则&#xff0c;因此常用的遍历方法有三种&#xff1a;DL…

二叉树的遍历详解

概述 二叉树的遍历是一个很常见的问题。二叉树的遍历方式主要有&#xff1a;先序遍历、中序遍历、后序遍历、层次遍历。先序、中序、后序其实指的是访问父节点的次序。在遍历过程中&#xff0c;若访问顺序是父节点-左孩子节点-右孩子节点&#xff0c;就是先序遍历&#xff0c;…

“二叉树遍历“详解 以及 二叉树的实现

目录 一.二叉树的遍历 1.二叉树的遍历的解释&#xff1a; 2.二叉树的遍历有三种递归结构 (1) 实现先序遍历&#xff1a; (2) 实现中序遍历&#xff1a; (3) 实现后序遍历&#xff1a; (4) 二叉树的层序遍历 层序遍历代码&#xff1a; 二.二叉树的递归实现相关函数讲解…

二叉树遍历详解

二叉树的遍历方式是最基本&#xff0c;也是最重要的一类题目&#xff0c;我们将从「前序」、「中序」、「后序」、「层序」四种遍历方式出发&#xff0c;总结他们的递归和迭代解法。 一、二叉树定义 二叉树&#xff08;Binary tree&#xff09;是树形结构的一个重要类型…

讲透学烂二叉树(三):二叉树的遍历图解算法步骤及JS代码

二叉树的遍历是指不重复地访问二叉树中所有结点&#xff0c;主要指非空二叉树&#xff0c;对于空二叉树则结束返回。 二叉树的遍历分为 深度优先遍历 先序遍历&#xff1a;根节点->左子树->右子树&#xff08;根左右&#xff09;&#xff0c;有的叫&#xff1a;前序遍历…

二叉树的中序遍历算法(Java三种实现方法)

文章目录 题目一、二叉树的节点定义二、三种遍历方法1.递归算法思想 2.迭代算法思想 3.Morris 中序遍历算法思想 总结 题目 给定一个二叉树的根节点 root &#xff0c;返回它的 中序 遍历 一、二叉树的节点定义 public class TreeNode {int val;TreeNode left;TreeNode righ…

二叉树遍历的几种常见方法

二叉树的遍历方法 一.二叉树分类&#xff1a; 完全二叉树满二叉树扩充二叉树平衡二叉树 二.二叉树的四种遍历方式&#xff1a; 前序遍历&#xff08;先根&#xff0c;再左&#xff0c;最后右&#xff09;中序遍历&#xff08;先左&#xff0c;再根&#xff0c;最后右&#…

二叉树的三种遍历方式

目录 1.二叉树的结构&#xff1a; 2.二叉树的前序遍历&#xff1a; 3.二叉树的中序遍历&#xff1a; 4.二叉树的后序遍历&#xff1a; 5.二叉树前、中、后序的代码实现&#xff1a; 前序遍历函数&#xff1a; 中序遍历函数&#xff1a; 后序遍历&#xff1a; 完整代码&am…

图解二叉树的三种遍历

1、二叉树的遍历 前序遍历&#xff1a;根结点 —> 左子树 —> 右子树 中序遍历&#xff1a;左子树—> 根结点 —> 右子树 后序遍历&#xff1a;左子树 —> 右子树 —> 根结点 层次遍历&#xff1a;仅仅需按层次遍历就可以 前序遍历&#xff1a;1 2 4 5 7…

二叉树的遍历【 详细讲解 】

二叉树的遍历 一共有4种遍历 先看图&#xff0c;对于这个图进行4种遍历的讲解 1、 先序遍历 定义&#xff1a;若二叉树为空&#xff0c;则空操作&#xff1b;否则 &#xff08;1&#xff09;访问根节点&#xff08;2&#xff09;先序遍历左子树&#xff08;3&#…

二叉树的创建及遍历方法

目录 1、二叉树的定义及特点 2、满二叉树和完全二叉树的概念 3、二叉树的存储结构 4、创建二叉树 5、树的四种遍历方法 6、结果及其分析 1、二叉树的定义及特点 二叉树是指树中节点的度不大于2的有序树&#xff0c;它是一种最简单且最重要的树。二叉树的递归定义为&#…

二叉树遍历(图解)

二叉树的顺序存储结构就是用一维数组存储二叉树中的节点&#xff0c;并且节点的存储位置&#xff0c;也就是数组的下标要能体现节点之间的逻辑关系。—–>一般只用于完全二叉树 链式存储—–>二叉链表 定义&#xff1a; lchild | data | rchild&#xff08;两个指针域&…

图解二叉树及二叉树遍历

二叉树及二叉树遍历 完全二叉树二叉树的遍历遍历的性质 1、完全二叉树 对于一棵具有n个节点的二叉树&#xff08;按层序编号&#xff09;&#xff0c;如果编号为i的节点与同样深度的满二叉树中编号为i的节点在二叉树的位置完全相同&#xff0c;则为完全二叉树。 换句话来说&a…

数据结构--二叉树遍历(详细过程)

目录 一、什么是二叉树&#xff1f; 二、二叉树的遍历 1. 先序遍历 2. 中序遍历 3.后序遍历 4. 遍历的推导 三、重要的事情 一、什么是二叉树&#xff1f; 1. 二叉树&#xff1a;一种树形结构&#xff0c;特点是每个结点至多只有两颗子树&#xff0c;并且子树有左右之分…