2024年Java最新面试必问的 JVM 类加载机制,你懂了吗?,面试题jvm类加载机制原理

总结

面试建议是,一定要自信,敢于表达,面试的时候我们对知识的掌握有时候很难面面俱到,把自己的思路说出来,而不是直接告诉面试官自己不懂,这也是可以加分的。

以上就是蚂蚁技术四面和HR面试题目,以下最新总结的最全,范围包含最全MySQL、Spring、Redis、JVM等最全面试题和答案,仅用于参考

一份还热乎的蚂蚁金服面经(已拿Offer)面试流程4轮技术面+1轮HR

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

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

这个类加载器负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。

2)扩展类加载器(Extension ClassLoader):

这个加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。

3)应用程序类加载器(Application ClassLoader):

这个类加载器由sun.misc.Launcher$AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

我们的应用程序都是由这3种类加载器互相配合进行加载的,如果有必要,还可以加入自己定义的类加载器。这些类加载器之间的关系一般如图所示。

3、什么是双亲委派模型?

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

类加载的源码如下:

protected Class<?> loadClass(String name, boolean resolve)

throws ClassNotFoundException

{

synchronized (getClassLoadingLock(name)) {

// 1、检查请求的类是否已经被加载过了

Class<?> c = findLoadedClass(name);

if (c == null) {

long t0 = System.nanoTime();

try {

// 2、将类加载请求先委托给父类加载器

if (parent != null) {

// 父类加载器不为空时,委托给父类加载进行加载

c = parent.loadClass(name, false);

} else {

// 父类加载器为空,则代表当前是Bootstrap,从Bootstrap中加载类

c = findBootstrapClassOrNull(name);

}

} catch (ClassNotFoundException e) {

// 如果父类加载器抛出ClassNotFoundException

// 说明父类加载器无法完成加载请求

}

if (c == null) {

// 3、在父类加载器无法加载的时候,再调用本身的findClass方法来进行类加载

long t1 = System.nanoTime();

c = findClass(name);

// this is the defining class loader; record the stats

sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);

sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);

sun.misc.PerfCounter.getFindClasses().increment();

}

}

if (resolve) {

resolveClass©;

}

return c;

}

}

4、为什么使用双亲委派模式?

1)使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是 Java 类随着它的类加载器一起具备了一种带有优先级的层次关系。

2)如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个java.lang.Object 的类,并放在程序的 ClassPath 中,那系统中将会出现多个不同的 Object 类,Java 类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。

5、有哪些场景破坏了双亲委派模型?

目前比较常见的场景主要有:

1)线程上下文类加载器,典型的:JDBC 使用线程上下文类加载器加载 Driver 实现类

2)Tomcat 的多 Web 应用程序

3)OSGI 实现模块化热部署

6、为什么要破坏双亲委派模型?

原因其实很简单,就是使用双亲委派模型无法满足需求了,因此只能破坏它,这边以面试常问的 Tomcat 为例。

我们知道 Tomcat 容器可以同时部署多个 Web 应用程序,多个 Web 应用程序很容易存在依赖同一个 jar 包,但是版本不一样的情况。例如应用1和应用2都依赖了 spring ,应用1使用的 3.2.* 版本,而应用2使用的是 4.3.* 版本。

如果遵循双亲委派模型,这个时候使用哪个版本了?

其实使用哪个版本都不行,很容易出现兼容性问题。因此,Tomcat 只能选择破坏双亲委派模型。

7、如何破坏双亲委派模型?

破坏双亲委派模型的思路都比较类似,这边以面试中常问到的 Tomcat 为例。

其实原理非常简单,我们可以看到上面的类加载方法源码(loadClass)的方法修饰符是 protected,因此我们只需以下几步就能破坏双亲委派模型。

1)继承 ClassLoader,Tomcat 中的 WebappClassLoader 继承 ClassLoader 的子类 URLClassLoader。

2)重写 loadClass 方法,实现自己的逻辑,不要每次都先委托给父类加载,例如可以先在本地加载,这样就破坏了双亲委派模型了。

8、Tomcat 的类加载器?

Tomcat 的类加载器如下图所示:

1)Bootstrap ClassLoader:可以看到上图中缺少了 Extension ClassLoader,在 Tomcat 中 Extension ClassLoader 被集成到了 Bootstrap ClassLoader 里面。

2)System ClassLoader 就是 Application ClassLoader:Tomcat 中的系统类加载器不会加载 CLASSPATH 环境变量的内容,而是从以下资源库构建 System 类加载器。

  • $CATALINA_HOME/bin/bootstrap.jar,包含用于初始化Tomcat服务器的 main() 方法,以及它所依赖的类加载器实现类。

  • $CATALINA_BASE/bin/tomcat-juli.jar 或 $CATALINA_HOME/bin/tomcat-juli.jar,日志实现类。

  • 如果 $CATALINA_BASE/bin 中存在 tomcat-juli.jar,则使用它来代替 $CATALINA_HOME/bin中的那个。

  • $CATALINA_HOME/bin/commons-daemon.jar

3)Common ClassLoader:从名字也看出来来了,主要包含一些通用的类,这些类对 Tomcat 内部类和所有 Web 应用程序都可见。

该类加载器搜索的位置由 $CATALINA_BASE/conf/catalina.properties 中的 common.loader 属性定义,默认设置将按照顺序搜索以下位置。

  • $CATALINA_BASE/lib 中未打包的类和资源

  • $CATALINA_BASE/lib 目录下的JAR 文件

  • $CATALINA_HOME/lib 中未打包的类和资源

  • $CATALINA_HOME/lib 目录下的JAR文件

4)WebappX ClassLoader:Tomcat 为每个部署的 Web 应用程序创建一个单独的类加载器,这样保证了不同应用之间是隔离的,类和资源对其他 Web 应用是不可见的。加载的路径如下:

  • Web应用的 /WEB-INF/classes 目录下的所有未打包的类和资源

  • Web应用的 /WEB-INF/lib 目录下的 JAR 文件中的类和资源

最后

由于篇幅限制,小编在此截出几张知识讲解的图解

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

xAvf1dpI-1714995887826)]

[外链图片转存中…(img-I8LYnd99-1714995887827)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值