美团财务科技Java后端一面:面向对象、类加载过程、全限定类名相同的类是否可以同时被加载

news2025/1/13 13:23:14

在这里插入图片描述

更多大厂面试内容可见 -> http://11come.cn

美团财务科技Java后端一面:面向对象、类加载过程、全限定类名相同的类是否可以同时被加载

如何理解面向对象?

面向对象 是具有对象概念的编程范式,面向对象将程序实现分为了一个个独立的对象,各个对象之间又互相调用, 将对象作为程序的基本单元抽取出来 ,提升了可维护性、可复用性、灵活性

为何需要面向对象设计思想?

在没有面向对象的时候,随着软硬件环境逐渐复杂,代码的可维护性很差,因此急需一种设计思想来提升软件的 可维护性

而面向对象的可复用性正解决了这个问题,因此面向对象逐渐成为程序开发中的主流思想

封装、继承、多态的优势

面向对象中的核心概念为:封装、继承、多态

封装 隐藏了对象内部的实现细节,对外暴露出一个接口供其他对象使用

继承 新创建的对象继承现有对象的属性和方法,提升代码复用性

多态 允许一个类有多种不同的实现形式,解耦调用方与实现方,提升程序灵活性

Java 程序从代码编写完到程序运行起来,它经历了什么样的一个过程?

Java 程序的加载是借助于 JVM 虚拟机来进行加载的,因此这里面试官考察的是 JVM 虚拟机的类加载过程

1、编写代码:开发人员编写的代码文件为 .java 文件,

2、编译代码:Java 编译器将 .java 文件编译为二进制的 .class 文件

接下来进入到 JVM 加载 .class 文件的流程,分为加载、链接、初始化三个阶段:

加载

1、通过二进制字节流加载 class 文件

2、创建该 class 文件在方法区的运行时数据结构

3、创建字节码对象 Class 对象

链接

1、验证:目的在于确保 class 文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性

主要包括四种验证:文件格式验证、元数据验证、字节码验证、符号引用验证

2、准备:为类变量(即静态变量)分配内存并且设置类变量的默认初始值,即零值。

这里不包含用 final 修饰的 static 变量,因为 final 修饰的变量在编译为 class 字节码文件的时候就会分配了,准备阶段会显式初始化

这里不会为实例变量分配初始化,类变量会分配在方法区,而实例变量是会随着对象一起分配到 Java 堆中

3、解析:将常量池内的符号引用转换为直接引用的过程

事实上,解析操作往往会伴随着 JVM 在执行完初始化之后再执行

符号引用就是一组符号来描述所引用的莫表。符号引用的字面量形式明确定义在《java虚拟机规范》的 Class 文件格式中。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。

解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等。

初始化

虚拟机在初始化阶段才真正开始执行类中编写的 Java 程序代码

初始化阶段就是执行类构造器 <clinit>() 方法的过程,<clinit>() 是 Javac 编译器自动生成的,该方法由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并生成的,如果一个类中没有静态代码块, 也没有变量赋值的动作,那么编译器可以不为这个类生成 <clinit>() 方法

之后 JVM 执行 Java 代码的 main() 方法,程序就开始执行

类是怎么被类加载器加载的?

采用双亲委派机制进行加载,JVM 在加载类的 class 文件时,Java虚拟机采用的是 双亲委派机制 ,即把请求交给父类加载器去加载

工作原理:

  1. 如果一个类加载器收到了类加载请求,他并不会自己先去加载,而是把这个请求委托给父类的加载器去执行
  2. 如果父类加载器也存在其父类加载器,则继续向上委托
  3. 如果父类加载器可以完成类加载任务,就成功返回;如果父类加载器无法完成类加载任务,则会由自家在其尝试自己去加载

优势:

  1. 避免类的重复加载
  2. 保护程序安全,防止核心API被篡改(例如,如果我们自定义一个java.lang.String类,然后我们去new String(),我们会发现创建的是jdk自带的String类,而不是我们自己创建的String类)

1702216110216

扩展:哪里打破了双亲委派机制?为什么要打破?

  • 在实际应用中,可能存在 JDK 的基础类需要调用用户代码,例如:SPI 就打破双亲委派模式(打破双亲委派意味着上级委托下级加载器去加载类)
    • 比如,数据库的驱动,Driver 接口定义在 JDK 中,但是其实现由各个数据库的服务上提供,由系统类加载器进行加载,此时就需要 启动类加载器 委托子类加载器去加载 Driver 接口的实现

两个全限定类名相同的类可以同时被加载吗?

两个全限定类名相同的类可以同时被加载

JVM 在确定类的唯一性时,不仅考虑类的全限定名,还考虑了类加载器。这意味着,即使两个类的全限定名相同,只要它们被不同的类加载器加载,它们就被视为不同的类

这里以 Tomcat 为例来解释 ,Tomcat 是可以部署多个应用的,那么多个应用之间就可能会出现全限定类名相同的类,如果不可以同时被加载,毫无疑问应用会出现问题

因此 Tomcat 是通过自定义类加载器类 实现了可以同时加载多个全限定类名相同的类

Tomcat 会为部署的每个应用都生成一个类加载器实例:WebAppClassLoader,这样每个应用就可以使用自己的类加载器去加载自己的类,从而达到应用之间的隔离,不会出现类冲突

Tomcat 还利用了自定义加载器实现了热部署功能: 因为 class 文件是由类加载器来完成的,如果 class 文件变更了,Tomcat 就会将原来的类加载器销毁,再创建新的类加载器来加载修改后的文件,以实现热部署功能

Tomcat 打破了 JVM 的双亲委派机制: 因为 Tomcat 为了保证应用之间类的隔离性,通过 WebAppClassLoader 加载当前应用下的 class 文件,不会委派给父类加载器,打破了双亲委派机制

Tomcat 中的类加载器如下图 ,上边的 3 个是 JVM 默认的类加载器,下边的是 Tomcat 中定义的类加载器

image-20240414191908701

堆和栈有什么区别?

是在 JVM 启动时创建的内存区域去实现对象、数组与运行时常量的内存分配,它是虚拟机管理最大的,也是垃圾回收的主要内存区域

堆

是存储了线程执行的方法,每个方法作为一个栈帧存储,栈帧存储了方法的局部变量表、操作数栈、动态链接和方法返回地址等信息

栈内存为线程私有的空间,每个方法在执行时都会创建一个栈帧,执行该方法时,就会将该方法所对应的栈帧入栈

栈

若程序OOM,该如何处理?

首先需要拿到 堆转储快照 进行分析,查看导致 OOM 的对象是否有必要存在,并且分析清除是因为哪些对象导致了 OOM

  • 如果是内存泄漏导致 OOM,可以查看泄露对象GC Roots的引用链,找到泄露对象在哪里被引用导致无法被回收

  • 如果不是内存泄漏,那么说明内存中的对象都是存活的,导致 OOM,这时应该检查虚拟机的堆内存设置是否有向上调整的空间。并且检查是否存在对象生命周期过长存储结构不合理的情况,减少程序运行中的内存消耗。

扩展:因为存储结构不合理而导致的堆内存溢出(来自于《深入理解Java虚拟机第3版》)

举例:使用 HashMap<Long, Long> 存储大量的数据,会导致浪费大量的空间,因为 HashMap 的空间效率使用太低。

对于一个 HashMap<Long, Long>来说,有效数据只有 Key、Value 的两个 long 型数据,占 16字节,long 数据被包装为 java.lang.Long 对象后,就分别具有 8 字节的 Mark Word、8字节的 Klass 指针、8字节的 long 型数值。两个 Long 对象组成 Map.Entry 之后,又多了 16 字节的对象头、8字节的 next 字段、4字节的 int 型的 hash 字段、4字节的空白填充(为了对齐)还有 HashMap 中对这个 Entry 的 8 字节的引用,这样实际占用的内存为:(Long(24byte) * 2) + Entry(32byte) + HashMap Ref(8byte)=88byte,空间效率仅仅为 16byte / 88byte = 18%。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue.js------Vue组件基础

能够理解Vue组件概念和作用能够掌握封装创建组件能力能够使用组件之间通信能够完成todo案例 一.Vue组件创建和使用 1.折叠面板-实现多个 创建一个文件夹demo 具体步骤请参考vue.js---vue基础 ⚫ 解决方案: 采用vue提供的单.vue文件-组件方式来封装一套然后复用 在component…

Hadoop的安装及配置

8.下面我们开始安装配置Hadoop 1&#xff09;首先下载hadoop-2.7.2的jar包 并添加到我们的jtxy1的/root/目录下 2&#xff09;yum install在线安装软件 yum install net-tools //支持ifconfig yum install vim //支持vim yum install glibc.i686 --java命令不好使 3&am…

人工智能论文GPT-3(2):2020.5 Language Models are Few-Shot Learners;微调;少样本Few-Shot (FS)

2 方法Approach 我们的基本预训练方法&#xff0c;包括模型、数据和训练&#xff0c;与GPT-2中描述的过程相似&#xff0c;只是模型规模、数据集规模和多样性&#xff0c;以及训练时长有所扩大&#xff0c;相对简单直接。 我们使用的上下文学习也与GPT-2相似&#xff0c;但在…

Web程序设计-实验03 JavaScript语言基础

题目 【实验主题】 素数问题求解。计算&#xff08;判断&#xff09; 1~100中哪些是素数、哪些是合数。 素数也称为质数&#xff0c;是只能被1及其自身整除的自然数。与素数相对应的是合数&#xff0c;合数可以被分解为若干个素数的乘积&#xff0c;这些素数称为这个合数的质…

即席查询笔记

文章目录 一、Kylin4.x1、Kylin概述1.1 定义1.2 Kylin 架构1.3 Kylin 特点1.4 Kylin4.0 升级 2、Kylin 环境搭建2.1 简介2.2 Spark 安装和部署2.3 Kylin 安装和部署2.4 Kylin 启动环境准备2.5 Kylin 启动和关闭 3、快速入门3.1 数据准备3.2 Kylin项目创建入门3.3 Hive 和 Kylin…

Qt Debug模式下应用程序输出界面乱码【已解决】

Qt Debug模式下应用程序输出乱码 一、问题描述二、解决方法三、相关测试 一、问题描述 源码为utf-8编码. Qt Creator在Debug模式下运行程序&#xff0c;下方应用程序输出界面显示乱码. 但正常运行无乱码&#xff1a; 二、解决方法 尝试修改文件编码、执行编码无果… 可参考…

架构师系列-搜索引擎ElasticSearch(十)- 索引别名及重建

索引别名 别名&#xff0c;有点类似数据库的视图&#xff0c;别名一般都会和一些过滤条件相结合&#xff0c;可以做到即使是同一个索引上&#xff0c;让不同人看到不同的数据。 别名的作用 在开发中&#xff0c;一般随着业务需求的迭代&#xff0c;较老的业务逻辑就要面临更新…

小型燃气站3D可视化:打造安全高效的燃气新时代

随着科技的不断进步&#xff0c;越来越多的行业开始融入3D可视化技术&#xff0c;燃气行业也不例外。 小型燃气站作为城市燃气供应的重要节点&#xff0c;其安全性和运行效率至关重要。传统的燃气站管理方式往往依赖于人工巡检和纸质记录&#xff0c;这种方式不仅效率低下&…

JVM 讲解 (主要类加载其以及流程和机制(双亲委派))

JVM有什么用&#xff1f; 说白了&#xff0c;就是我们编写 Java 代码&#xff0c;编译 Java 代码&#xff0c;目的不是让它在 Linux、Windows 或者 MacOS 上跑&#xff0c;而是在 JVM 上跑。&#xff08;保证只要有JVM这个东西&#xff0c;就可以跨平台使用Java) 可以把JVM想象…

事务的传播行为介绍和事务失效

常用的就下图介绍的这两种&#xff0c;REQUIRED 支持当前事务&#xff0c;如果不存在&#xff0c;就新建一个&#xff0c;EQUIRES_NEW 如果有事务存在&#xff0c;挂起当前事务&#xff0c;创建一个新的事务 同一个service中必须用代理对象调用&#xff0c;否则失效

ADOP 万兆电口光模块:SFP+转RJ45端口解决方案

&#x1f335;在数据中心的接入层中&#xff0c;大多数服务器网卡&#xff08;NIC&#xff09;和存储设备都采用10GBASE-T RJ45端口&#xff0c;而与之相连的TOR&#xff08;机架顶部&#xff09;交换机通常配备SFP端口&#xff0c;且二者无法直接相连。为了解决该问题&#xf…

软考高级架构师:项目配置管理中产品配置例题

题目 项目配置管理中&#xff0c;产品配置是指一个产品在其生命周期各个阶段所产生的各种形 式和各种版本的文档、计算机程序、部件及数据的集合。该集合中的每一个元素 称为该产品配置中的 一个配置项&#xff0c; ( )不属于产品组成部分工作成果的配置项。 A需求文档 B设计文…

Redis中的事务(二)

事务 事务的实现 执行事务 当一个处于事务状态的客户端向服务器发送EXEC命令时&#xff0c;这个EXEC命令将立即被服务器执行&#xff0c;服务器会遍历这个客户端的事务队列&#xff0c;执行队列中保存的所有命令&#xff0c;最后将执行命令所得的结果全部返回给客户端。 例…

3、MYSQL-一条sql如何在MYSQL中执行的

MySQL的内部组件结构 大体来说&#xff0c;MySQL 可以分为 Server 层和存储引擎层两部分。 Server层 主要包括连接器、查询缓存、分析器、优化器、执行器等&#xff0c;涵盖 MySQL 的大多数核心服务功能&#xff0c;以及所有的内置函数&#xff08;如日期、时间、数学和加密函…

MIMO(多天线)通信的四种译码算法

目录 一. 介绍 二. 极大似然译码 三. 破零译码算法 四. 最小均方误差算法 五. 球形译码 一. 介绍 发射天线数记为Mt&#xff0c;接收天线数记为Mr。由此发射信号x为向量&#xff1a; 接受信号y为向量&#xff1a; 信道H为矩阵&#xff1a; 利用n代表噪声向量&#xff0c;…

【若依前后端分离】温湿度仪表盘

示例&#xff1a; 代码&#xff1a; TemperatureAndHumidity.vue组件 //温湿度仪表盘 <template><div><!-- 在这里放置你的图表组件 --><div ref"echarts" style"width: 100%; height: 400px;"></div></div> </t…

【C++干货基地】面向对象核心概念 const成员函数 | 初始化列表 | explicit关键字 | 取地址重载

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

数据结构PT1——线性表/链表

1&#xff1a;顺序存储实现(数组实现) Data&#xff1a; a1 a2 .....ai ai1 .... an .... typedef struct LNode *List; //指向LNode的指针&#xff0c;这是typedef的&#xff0c;你可以随时声明&#xff0c;而不加typedef只是创建一个 struct LNode{ //结构体成员ElementT…

Sentinel 流控注解使用

大概原理&#xff1a;通过反射解析注解 SentinelResource信息完成调用&#xff0c;处理方法&#xff0c;类似AOP编程 处理方法的返回类型要保持一致&#xff0c;参数和顺序保持一致&#xff0c; 可以在参数列表最后加 com.alibaba.csp.sentinel.slots.block.BlockException; …

【leetcode面试经典150题】62. K 个一组翻转链表(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…