《面试1v1》类加载过程

我是 javapub,一名 Markdown 程序员从👨‍💻,八股文种子选手。

面试官: 你了解Java的类加载过程吗?跟我聊聊classes是如何加载到JVM中的。

候选人: Java的类加载过程由加载、验证、准备、解析和初始化5个阶段组成。当我们使用java命令执行一个类时,JVM会首先搜索类的加载路径,这包括Bootstrap Classpath、Extension Classpath和Application Classpath。

面试官: 哈哈,这也太官方了吧,来,我们以更口语的方式探讨下类加载过程。想象你是一名新手Java程序员,刚入职一个公司,被分配一个任务需要执行一个Java类,你会有什么疑惑或者过程?

候选人: 好的,那我来思考下当初我第一次运行Java程序的时候的内心活动:
天啊,我首先得搞清楚要运行的这个类到底在哪儿?难道要我一个个文件翻找吗?那还不如让我直接读JVM的源码来找呢!
Wait,原来JVM已经把这事儿都帮我干了,它会去找 classpath 下的文件,包括环境变量里设置的那堆classpath。这肯定是个苦力活,幸好有JVM这个工具哥帮忙!
找到类文件了,接下来JVM该干嘛?嗯,它得确定这个类里写的是否都是正确的Java语法,不会误导小菜鸟我。它会进行类文件的验证,确保我的Java程序没有安全隐患!
验证通过了,JVM该准备干啥?它需要为类中的静态变量分配内存并设置默认初始值,这个过程就是准备阶段。
静态变量有内存了,JVM还需要干什么?嗯,它得解析类文件里的符号引用,像是类名、方法名、变量名等,把这些符号转成直接引用,方便后续调用。这就是解析阶段。
最后,JVM要真正帮我干活了,它要执行类构造器()方法的字节码,给静态变量复杂的初始值。这就是初始化阶段。
Initialization of 类名 complete! 我的任务终于可以开始执行了!真不容易,还得感谢JVM这位大恩人。

面试官: 哈哈,这个解释我喜欢!inclusion of源代码和动态的思考过程增加了解释的轻松和趣味性。你这种围绕一个场景作解释的方式很形象,让人容易理解,这在技术面试中是很重要的一点。

候选人: 谢谢面试官的夸奖!我也觉得把一个复杂的技术问题变成一个故事或场景会让人更容易理解其中的逻辑和流程。这也是我在博客和公众号里常用的一种讲解方式,很高兴面试官能够欣赏!

面试官: 那我们继续聊聊类加载过程中最重要的几个类吧,什么类负责 finding 和loading 操作?

候选人: 在类加载过程中,ClassLoader 类及其子类负责finding和loading操作。

面试官: 是的,ClassLoader是一个很重要的类。那么默认的ClassLoader又有哪几个?

候选人: 默认有3个ClassLoader:

  1. Bootstrap ClassLoader 启动类加载器:负责加载JDK内置的类,如rt.jar等。
  2. Extension ClassLoader 扩展类加载器:负责加载JDK扩展目录中的jar包、以及VM指定的其他jar包。
  3. App ClassLoader 应用程序类加载器:负责加载用户自定义的类。
//JDK源码中ClassLoader的继承关系
public class ClassLoader {
    public ClassLoader() {} 
    public Class<?> loadClass(String name) {...}
}
public class SecureClassLoader extends ClassLoader {...} 
public class URLClassLoader extends SecureClassLoader {...} 
//和类加载息息相关的其他类 
public final class Class<T> {...}  
public class ClassNotFoundException extends Exception {...}

面试官: ClassLoader的加载顺序遵循什么规则?

候选人: ClassLoader遵循父类委派模式,当一个类加载器收到类加载请求时,它会把这个请求委派给它的父类加载器去完成,依此形成一个链条。只有父类加载器在它的搜索范围内无法找到所需的类时,子加载器才会尝试自己去加载这个类。
因此,类加载的顺序为:

  1. Bootstrap ClassLoader
  2. Extension ClassLoader
  3. App ClassLoader
    如果父类可以完成类加载工作则子类不会再去加载,否则子类才会负责加载。这种委派机制可以避免重复加载,也有利于安全性。

面试官: 很好,你对Java类加载机制有很深入的理解。最后,我们聊一聊类加载过程的双亲委派模型在哪些方面带来的好处?

候选人: 类加载双亲委派模型带来的好处主要有两点:

  1. 避免重复加载:当父类已经加载了某个类时,子类不会再重复加载该类,从而避免资源消耗。
  2. 安全性:父类加载的类被所有的子类所信任。 strs如果子类可以随意加载,那么就可能加载一个非授权版本的类,破坏安全性。
    综上,双亲委派模型体现了“安全第一,不重复加载”的设计思想,这两点好处使得Java类加载机制更加完备和安全。

面试官: 很好,你的回答很全面和到位。

候选人: 非常感谢面试官的指导。

面试官: 你的谢意我心领了,我们的对话也达到了我的目的。真诚地希望这些知识能在你的工作中派上用场。加油!

候选人: 非常感谢面试官的鼓励!我会努力运用所学的知识,在工作实践中不断进步。也祝面试官心想事成

面试官: 好,让我们继续讨论类加载过程中另一个重要概念:类的生命周期。什么是类的生命周期?它包括哪几个阶段?

候选人: 类的生命周期描述了一个类从被加载到被卸载的整个过程。它主要包括:

  1. 加载:找寻并加载类的二进制数据,将其读入内存,并为之创建一个Class对象。
  2. 链接:验证、准备和解析。验证是否有正确的内部结构,并和其他类保持一致性。准备分配内存并设置初始值。把相关的符号引用转换为直接引用。
  3. 初始化:执行类构造器()方法的字节码,给类的静态变量赋予正确的初始值。
  4. 使用:程序使用这个类创建实例对象、访问类的静态变量和方法等。
  5. 卸载:GC回收这个类的所有实例和空间。卸载该类的字节码,并从运行时常量池中移除这个类的符号引用。

面试官: 说明的很详细。类的生命周期中,有哪几个阶段会触发类初始化?

候选人: 有三种情况会触发类的初始化:

  1. 新创建一个该类的实例。
  2. 访问该类的静态变量,或为静态变量赋值。
  3. 调用该类的静态方法。
    除此之外,下面这些操作不会触发类的初始化:
  4. 使用一个类的名称,如在变量声明中使用该类的名称。
  5. 使用类加载器加载一个类。
  6. 访问某个类的静态常量。
//举例
public class Test {
    public static int a = 1;  //静态变量,会触发初始化
    public static final int b = 2;   //静态常量,不会触发初始化
    public static void method(){}   //静态方法,会触发初始化
}
Test t = new Test();   //创建实例,会触发初始化
Test.a = 2;           //访问静态变量,会触发初始化
Test.b = 3;           //访问静态常量,不会触发初始化
Test.method();        //调用静态方法,会触发初始化  

面试官: 说的很清楚,举例也很形象。那静态代码块是在哪个阶段执行的?

候选人: 静态代码块是在类初始化阶段执行的,位于()方法中。它优先于构造方法执行,并且只执行一次。例如:

public class Test {
    static {
        System.out.println("静态代码块执行");
    } 
    public Test() {
        System.out.println("构造方法执行");
    }
}

Test t1 = new Test();  
//打印:
静态代码块执行  
构造方法执行  

Test t2 = new Test();
//打印:
构造方法执行

因此,静态代码块主要用于一次性地对类进行初始化设置,这些设置只在类第一次被加载时执行。它和构造方法的不同之处在于,构造方法在每次创建实例时都会执行。

面试官: 很好,你对类的生命周期及其与类初始化的关系理解很透彻。我想你应该可以轻松应付与类加载相关的面试题了!

候选人: 非常感谢面试官的提问,这些关于类的生命周期和初始化阶段的知识点对我来说均很重要。我会不断复习和运用这些知识,以便进一步熟练掌握类加载机制的相关原理,从而应对可能遇到的面试题和实际开发中的相关问题。

最近我在更新《面试1v1》系列文章,主要以场景化的方式,讲解我们在面试中遇到的问题,致力于让每一位工程师拿到自己心仪的offer,感兴趣可以关注JavaPub追更!


《面试1v1》 连载中…


🎁目录合集:

Gitee:https://gitee.com/rodert/JavaPub

GitHub:https://github.com/Rodert/JavaPub

http://javapub.net.cn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/25559.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JAVA变量在不同情况下未赋值与默认初始值

目录 一、默认初始值 二、本地变量 代码 运行结果 二、实例变量 代码 运行结果 三、本地变量和实例变量的区别 1.作用域 2.生命周期 3.初始化 一、默认初始值 数据类型初始值数据类型初始值byte0long0Lchar‘u0000’float0.0fshort0double0.0int0booleanfalse引用nul…

【react全家桶】react-Hook (下)

本人大二学生一枚&#xff0c;热爱前端&#xff0c;欢迎来交流学习哦&#xff0c;一起来学习吧。 <专栏推荐> &#x1f525;&#xff1a;js专栏 &#x1f525;&#xff1a;vue专栏 &#x1f525;&#xff1a;react专栏 文章目录 15【react-Hook &#xff08;下&#x…

普源1G带宽4通道10G采样率数字示波器MSO8104

超高性价比七合一 集成示波器在如今的集成设计领域&#xff0c;一款集成度较高的综合示波器已经成为设计工程师必不可少的得力工具。 MSO8000 系列数字示波器&#xff0c;它集 7 种独立仪器于一体&#xff0c;包括一台示波器、一台 16 通道逻辑分析仪、一台频谱分析仪、一台任…

ipad触控笔是哪几款?一般电容笔和Apple pencil区别

和苹果Pencil最大的区别就是&#xff0c;电容笔没具备重力压感&#xff0c;只有一种倾斜的压感。如果你不经常画画&#xff0c;那么你可以使用一款平替电容笔。这种平替电容笔&#xff0c;不仅仅是用在办公上&#xff0c;还能用来做笔记和练习。更何况&#xff0c;现在苹果一款…

【密码学复习】第十章 身份鉴别

身份鉴别的定义 定义&#xff1a;身份鉴别&#xff0c;又称为身份识别、身份认证。它是证实客户的真实身份与其所声称的身份是否相符的过程。 口令身份鉴别 固定口令&#xff08;四&#xff09; 注册环节&#xff1a;双因子认证 ① 接收用户提供的口令pw&#xff08;PIN&…

JVM-基础知识

JVM基础知识 JVM结构图 字节码文件 Java虚拟机不和包括Java在内的任何语言绑定,它只与字节码文件这种特定的二进制文件格式所关联. Class文件结构不仅仅是JVM的执行入口,更是Java生态圈的基础和核心. 字节码文件内容是什么 字节码是一种二进制的类文件,他的内容是JVM指令,而…

github在线编程

github在线编程 文章目录 github在线编程两种区别演示项目 Ruoyi-VueGitHub Codespaces 演示github 访问项目使用 GitHubCodeSpace 打开该项目查看运行环境安装运行环境初始化myql数据安装 redis运行前端运行后端前后端运行成功测试安装相关插件 GitPod 演示 说明: 目前总结 gi…

把玩数据在内存中的存储

前言&#xff1a;时光如梭&#x1f4a6;&#xff0c;今天到了C语言进阶啦&#x1f60e;&#xff0c;基础知识我们已经有了初步认识&#xff0c; 是时候该拔高拔高自己了&#x1f63c;。 目标&#xff1a;掌握浮点数在内存的存储&#xff0c;整形在内存的存储。 鸡汤&#xff1a…

好玩!AI文字RPG游戏;播客进入全AI时代?LangChain项目实践手册;OpenAI联创科普GPT | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; Microsoft Build 中国黑客松挑战赛&#xff0c;进入AI新纪元 近期&#xff0c;伴随着人工智能的新一轮浪潮&#xff0c;Hackathon (黑…

【网络协议详解】——OSPF协议(学习笔记)

目录 &#x1f552; 1. 概述&#x1f552; 2. 相关概念&#x1f558; 2.1 基本思想&#x1f558; 2.2 区域及路由&#x1f558; 2.3 链路状态数据库&#x1f564; 2.3.1 点到点网络&#x1f564; 2.3.2 点到多点网络&#x1f564; 2.3.3 广播网络与非广播多址接入网络&#x1f…

反射枚举

1、定义 java的反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能直到这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用他的任意方法和属性&#xff0c;既然能够拿到那么&#xff0c;我们就可以修改部分类型信息&#xff1b;这种动…

软考A计划-电子商务设计师-计算机系统基础知识

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

Delphi11的多线程ⓞ,附送图片处理代码

Delphi11的多线程ⓞ OLD Coder , 习惯使用Pascal 接下来准备启用多线程&#xff0c;毕竟硬件多核&#xff0c;Timer不太爽了&#xff08;曾经的桌面&#xff0c;都是Timer——理解为“片”&#xff09; 突然想写写&#xff0c;不知道还有多少D兄弟们在。 从源码开始 用D11之…

mybatisplus递归传递多个参数 | mybatisplus传递多个参数获取层级数据 | mybatisplus传递多个参数获取树形数据

搜索关键字&#xff1a; mybatisplus关联查询传递参数|"select""树形结构"|"select""树形结构""传参"| "select""many""传参"| "select""column""传参" 1、…

内置工具横向移动

IPCSchtasks IPC: IPC$是共享"命令管道"的资源&#xff0c;它是为了让进程通信而开放的命名管道&#xff0c;连接双方可以建立安全的通道并以此通道进行加密数据交换&#xff0c;从而实现对远程计算机的访问。 利用条件&#xff1a; 1、开放139、445 2、目标开启…

SAP-MM-采购申请审批那些事!

1、ME55不能审批删除行项目的PR 采购申请审批可以设置行项目审批或抬头审批。如果设置为抬头审批时&#xff0c;ME55集中审批时&#xff0c;就会发现有些采购申请时不能审批的&#xff0c; 那么这些采购申请时真的不需要审批么&#xff1f;不是的&#xff0c;经过核对这些采购申…

【每周一书】--(认知觉醒)思考:如何用清爽的情绪面对内卷的当下?

【每周一书】--&#xff08;认知觉醒&#xff09;思考&#xff1a;如何用清爽的情绪面对内卷的当下&#xff1f; 认知觉醒&#xff1a;开启自我改变的原动力焦虑&#xff1a;焦虑的根源完成焦虑定位焦虑选择焦虑环境焦虑难度焦虑 如何拥有清爽的情绪&#xff0c;释放焦虑情绪 认…

STM32F407单片机HAL库CAN2不能接收数据解决方法

最近在使用stm32F407的片子调试can通信&#xff0c;直接在正点原子的代码上修改调试&#xff0c;调试can1的时候&#xff0c;基本没啥问题&#xff0c;收发都正常&#xff0c;使用查询模式和中断模式都可以。但是当修改到can2的时候&#xff0c;可以正常发送数据&#xff0c;但…

WPF 热重载失效了

关于 热重载官方说明&#xff1a; WPF 和 UWP 应用的 XAML 热重载是什么Introducing the .NET Hot Reload experience for editing code at runtime 热重载简单来说&#xff0c;就是点击运行程序后&#xff0c;修改 XAML 代码&#xff0c;应用程序会实时的显示你的修改 为…

Python入门(十三)函数(一)

函数&#xff08;一&#xff09; 1.函数概述2.函数定义2.1向函数传递信息2.2实参和形参 作者&#xff1a;xiou 1.函数概述 函数是带名字的代码块&#xff0c;用于完成具体的工作。要执行函数定义的特定任务&#xff0c;可调用该函数。需要在程序中多次执行同一项任务时&#…