JVM高频面试题

1、项目中什么情况下会内存溢出,怎么解决?

	(1)误用固定大小线程池导致内存溢出  Excutors.newFixedThreadPool内最大线程数是21亿
	  (2) 误用带缓冲线程池导致内存溢出最大线程数是21亿
	  (3)一次查询太多的数据,导致内存占用太大
	  (4)动态生成类导致内存溢出

2、类加载过程?

三个过程:
	加载:

JVM高频面试题_第1张图片
链接:
JVM高频面试题_第2张图片
链接又分为:验证、准备、解析

	初始化:

在这里插入图片描述
总结:所谓类加载机制就是:虚拟机把Class文件加载到内存,并对数据进行校验、转换解析和初始化,形成虚拟机可以直接使用的Java类型,即java.lang.class

补充:类.class只会触发类加载且只会加载一次,而new 类()则会触发类初始化。静态变量的赋值在初始化时完成。

3、什么是双亲委派?
在这里插入图片描述

4.对象引用分为哪几类?

	1.强引用

在这里插入图片描述
正常对象引用

		2.软引用

在这里插入图片描述
系统内存足够时不会被回收,不足时才会被回收。且若回收之后仍内存不够,则会内存溢出
3.弱引用
在这里插入图片描述
无论内存是否充足都会被回收
4.虚引用
JVM高频面试题_第3张图片
主要用来跟踪对象被垃圾回收的过程,任何时候都可能被垃圾回收

5、堆(heap)和栈(stack)有什么区别?
1、内存分配方式不同:堆是动态分配内存空间的;栈是静态分配内存空间的。
2、内存空间大小不同:堆的内存空间通常比较大,可以动态扩展;而栈的内存空间通常比较小,由于静态分配,所以大小固定。
3、内存分配效率不同:堆的内存分配效率相对较低,因为需要进行垃圾回收和内存整理等操作;而栈的内存分配效率相对较高,因为只需要简单地移动指针即可。
4、存储内容不同:堆用于存储对象实例和数组等动态数据,它具有很好的灵活性;而栈用于存储方法调用的局部变量和操作数栈等数据,它具有很好的局部性和快速访问的特点。

6、什么情况下会发生栈内存溢出?

方法调用层次过深:如果方法调用层次过深,每次方法调用都会在栈中创建一个新的栈帧,如果栈空间不足,就会导致栈内存溢出。
局部变量过多:如果方法中定义了大量的局部变量,也会占用栈空间,如果栈空间不足,就会导致栈内存溢出。
递归调用:递归调用会不断地向栈中添加新的方法调用,如果递归深度过大,就会导致栈内存溢出。
参数传递过多:如果方法参数传递过多,也会占用栈空间,如果栈空间不足,就会导致栈内存溢出。
大量线程调用:如果同时有大量的线程在栈中进行方法调用,也会占用栈空间,如果栈空间不足,就会导致栈内存溢出。

7、什么是OOM?
OOM 是 OutOfMemoryError 的缩写,是指在 Java 程序运行期间,由于内存不足而导致程序出现错误的情况。OOM 错误通常分为堆内存溢出和非堆内存溢出两种情况。

8、如何判断一个对象是否存活?

	1、引用计数法:引用计数法是一种简单的垃圾回收算法,它通过统计对象的引用计数,来判断对象是否存活。每当一个对象被引用时,它的引用计数加 1,当一个对象的引用计数为 0 时,说明该对象已经不再被使用,可以被垃圾回收器回收。但是,引用计数法无法处理循环引用的情况,即两个或多个对象相互引用,导致它们的引用计数都不为 0,无法被回收。
	2、可达性分析法:可达性分析法是一种常用的垃圾回收算法,它通过从一组根对象开始,查找所有被这组根对象所引用的对象,以此来确定哪些对象是存活的。在可达性分析法中,根对象可以是程序中的静态变量、本地变量或者正在执行的线程等。当一个对象无法被根对象所引用时,说明该对象已经不再被使用,可以被垃圾回收器回收。

可达性分析法是 Java 中常用的判断对象存活的方式,它考虑了对象之间的引用关系,可以处理循环引用的情况,而引用计数法则无法处理循环引用的情况,因此在 Java 中并不采用引用计数法来判断对象是否存活。

9、有哪几种垃圾回收器?各自的优点是什么?
Serial 垃圾回收器:是一种单线程的垃圾回收器,它使用标记-清除算法来回收垃圾对象。优点是简单高效,适合小型应用场景,但是在多核处理器上的表现较差。

Parallel 垃圾回收器:是一种多线程的垃圾回收器,它使用标记-整理算法来回收垃圾对象。优点是在多核处理器上的表现比 Serial 垃圾回收器更好,适合中型应用场景。

CMS 垃圾回收器:是一种并发的垃圾回收器,它使用标记-清除算法来回收垃圾对象。优点是回收效率高,暂停时间短,适合大型应用场景。但是,CMS 垃圾回收器会产生内存碎片,可能会导致频繁的 Full GC,影响应用性能。

G1 垃圾回收器:是一种并发的垃圾回收器,它使用标记-整理算法来回收垃圾对象。优点是在大型应用场景下表现良好,可以有效避免内存碎片和频繁的 Full GC。同时,G1 垃圾回收器还支持设置可预测的暂停时间,使得应用程序的性能得到进一步优化。可以优先回收大块垃圾的区域

Serial和CMS都是标记清楚,Parallel和G1都是标记整理。G1现在用的最多。

10、什么是JVM内存结构?
JVM分为堆、虚拟机栈、本地方法栈、程序计数器、方法区

虚拟机栈里有局部变量表、操作数栈、动态链接、方法返回信息

本地方法栈:是C栈,执行本地方法

程序计数器:用于记录当前虚拟机正执行的线程指令地址

堆:所有线程共享的一块内存,虚拟机开启时就创建,可通过GC进行回收。

方法区:jdk1.8之后叫元数据区

11、说说垃圾回收算法?
标记清除法:利用可达性去标记存活对象和垃圾对象,然后遍历把标记对象回收。(效率不行,还会产生不连续的空间分片)
标记整理法:还是先遍历标记,然后把存活的向一边移动,空出来的另一边的回收掉。(适用存活多,垃圾少,无空间碎片产生)
标记复制法:把内存分为大小相等的两块,每次只用一块,用完了,就把存活对象转到另一块,这一块就移除。(无空间碎片,内存使用率低)
分代收集算法:在java虚拟机中把内存分为新生代和老年代。新生代中有大量死去和少量存活对象,用标记复制法,这样复制存活对象成本低,而老年代中对象存活率高,所以采用标记清除或标记整理
12、什么是类加载器?常见类加载器有哪些?
通过一个类的全限定类名来获取该类的二进制字节流叫做类加载器
启动类加载器:用来加载java核心类库,无法被程序直接引用。
扩展类加载器:加载java扩展库
系统类加载器:根据java的类路径来加载类,java应用类都是它加载的
自定义类加载器:java语言实现,继承自ClassLoader
JVM高频面试题_第4张图片

你可能感兴趣的:(Java,jvm,java,面试)