0
点赞
收藏
分享

微信扫一扫

#yyds干货盘点# 别再问我Java虚拟机八股文了!

phpworkerman 2022-02-21 阅读 87

本期是【大厂面试】系列文章的第8期,模拟Java虚拟机基础知识高频面试题目。

面试开始

面试官今天聊聊Java虚拟机吧面试官知道什么是堆吗?

大彬​:堆用于存放对象实例,是垃圾收集器管理的主要区域,因此也被称作​​GC​​​堆。堆可以细分为:新生代(​​Eden​​​空间、​​From Survivor​​​、​​To Survivor​​空间)和老年代。

面试官嗯,说一下堆栈的区别?

独白:哈哈,这个简单啦~

大彬:1、堆的物理地址分配是不连续的,性能较慢;栈的物理地址分配是连续的,性能相对较快。

大彬:2、堆存放的是对象的实例和数组;栈存放的是局部变量,操作数栈,返回结果等。

大彬:3、堆是线程共享的;栈是线程私有的。

面试官了解双亲委派模型吗?

独白:老八股文了哈哈

大彬:当类载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求委派给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。

#yyds干货盘点# 别再问我Java虚拟机八股文了!_java

大彬​:双亲委派模型的具体实现代码在 ​​java.lang.ClassLoader​​​中,此类的 ​​loadClass()​​​ 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 ​​ClassNotFoundException​​,此时尝试自己去加载。源码如下:

public abstract class ClassLoader {
// The parent class loader for delegation
private final ClassLoader parent;

public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}

if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}

protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
}

面试那你觉得为什么需要双亲委派模型呢?大彬:假如没有双亲委派模型而是由各个类加载器自行加载的话,内存里面可能会出现多个相同的类。

大彬:比如用户编写了一个​​java.lang.Object​​的同名类并放在​​ClassPath​​中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的​​Object​​类,那么类之间的比较结果及类的唯一性将无法保证。

面试官刚提到类加载器,什么是类加载器呢?

大彬​:类加载器就是加载所有的类的工具,它加载的类在内存中只会存在一份,也就是堆中的Class对象。不可以重复加载

大彬:Java 文件在经过 Java 编译器编译之后就被转换成 Java 字节码(class 文件)。类加载器负责读取 Java 字节码,并转换成 ​​java.lang.Class​​类的一个实例。

面试官嗯,那你知道有哪些类加载器吗?

独白:没完没了了...

大彬:主要有以下四种类加载器:

  • 启动类加载器:用来加载 Java 核心类库,无法被 Java 程序直接引用。
  • 扩展类加载器:它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
  • 系统类加载器:它根据应用的类路径来加载 Java 类。可通过​​ClassLoader.getSystemClassLoader()​​获取它。
  • 自定义类加载器:通过继承​​java.lang.ClassLoader​​类的方式实现。

面试官好,怎么判断一个对象是否存活?

大彬​:嗯,JVM对堆垃圾回收前的第一步就是要判断那些对象已经死亡(即不再被任何途径引用的对象)。

大彬:判断对象是否存活有两种方法:引用计数法和可达性分析。

大彬:先讲讲引用计数法。给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。

大彬:然后是可达性分析。通过​​GC Root​​对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到​​GC Root​​没有任何的引用链相连时,说明这个对象是不可用的。

#yyds干货盘点# 别再问我Java虚拟机八股文了!_java_02

面试官​:那可以作为GC Roots的对象有哪些呢?大彬:主要有四种对象。

  1. 虚拟机栈中引用的对象
  2. 本地方法栈中Native方法引用的对象
  3. 方法区中类静态属性引用的对象
  4. 方法区中常量引用的对象

面试官:不错,今天面试就到这吧

独白:本期JVM专题内容相对基础,后续会更新JVM调优、垃圾收集器、内存分配策略等内容,敬请期待~

举报

相关推荐

Java八股文

java八股文

JAVA八股文

Java八股文(Docker)

Java面试八股文

【八股文】Java基础

Java 八股文 - MySQL

0 条评论