0


JVM常问面试题(自答版)

1.什么是堆?

堆是用来储存对象实例的区域,同时也是OOM最容易发生的区域和垃圾收集器管理的主要区域,所以也称为GC堆,可以分为新生代(Eden,ToSurvivor和FromSurvivor)和老年代。

2.堆和栈的区别

1.堆的物理地址是不连续的,栈的物理地址是连续的,所以栈的性能会比较快

2.堆存放的是对象实例和数组,栈存放的是局部变量,操作数栈和返回结果

3.堆是线程共享的,栈是线程私有的

3.堆栈溢出

堆内存溢出:当创建的对象占空间超过最大堆容量时就会抛出OOM

栈内存溢出:当请求的栈溢出,导致内存耗尽就会抛出SOF,一般是线程嵌套方法过多,导致栈帧过多,常出现于递归方法中

4.元空间和永久代的区别

在JAVA8中永久代已经被删除,取而代之的是元空间(MetaSpace),元空间和永久代最大的区别就是:元空间不在虚拟机中,而是使用本地内存。类的字符串常量和静态变量存于堆中,其他内容(类元信息,字段,静态属性,常量等)都存于元空间中

5.什么是双亲委派模型

当一个类加载器收到一个类的加载请求的时候,它并不会立刻去加载,而是会向父类加载器发出请求,被询问的高层次加载器都会思考两个问题:我是否加载过此类?我是否能加载此类?当所有高层次加载器对两个问题答案都为否的时候,才会让该加载器来加载这个类,此机制的好处在于能避免重复加载同一个类,保证数据安全

6.如何打破双亲委派机制

打破原因:有时候我们需要自定义加载器来加载这个类,而不是向上委托,当所有高层次加载器都不能加载时才让该加载器来加载

打破方法:重写ClassLoader中的loadClass()方法

7.有哪些类加载器

1.应用类加载器(Application ClassLoader):加载用户定义的CLASSPATH路径下的类

2.平台类加载器(拓展类加载器Platform ClassLoader):加载拓展的系统类(XML,加密,压缩相关功能类)

3.系统类加载器(Bootstrap):加载最核心的JAVA类

4.自定义加载器

8.类加载过程

第一步:Load阶段,读取类文件,产生二进制流并形成数据结构,初步校验(如cafe babe魔法数,常量池等),创建对应类的实例

第二步:Link阶段,分为三个步骤

1.验证:更详细的检验class文件的正确性

2.准备:为静态变量分配内存空间

3.解析:将常量池中的符号引用替换为直接引用

第三步:Init阶段:初始化工作

9.如何判断对象是否存活

引用计数法和可达性分析

引用计数法:在对象中加入计数器,当被引用时+1,取消引用时-1,当计数为0是说明这个对象不再存活了

可达性分析:从GC Root对象为起点,从节点向下搜索,其路径称为引用链,当引用链没有经过该对象,说明该对象不存活

10.哪些对象可以成为GC Root对象

虚拟机栈中引用的对象,本地方法栈中引用的对象,类静态属性中引用的对象,常量引用的对象

11.垃圾回收相关算法

“标记——清除算法”:从GC Roots出发,标记有引用的对象,没有标记的删除(缺点:会产生大量空间碎片)

“标记——整理算法”:从GC Roots触发,标记存活的对象,将存活对象整理到内存空间的一端,形成连续的已使用空间,将之外的部分清理掉

“Mark——Copy算法”(主流的YGC算法):将内存空间分为两块,任何时间只有一块区域激活,回收时将存活对象复制到另一区域,将该区域标为激活,原区域清除并且变为未激活

12.常见的垃圾回收器

Serial:主要用于YGC的垃圾回收器,串行单线程完成GC任务,会产生STW(“Stop The World”使整个应用程序暂停),由于FGC的时间比较长,STW会严重影响性能

ParNew:Serial的多线程版本,基本没有太大区别

Parallel:与ParNew同样是多线程的回收器,但是以吞吐量优先,可以牺牲时间换取吞吐量

CMS:初始标记(STW)——并发标记——重新标记(STW)——并发清除(采用“标记——清除算法”会产生大量空间碎片,可以配置JVM在FGC完成后对老年代进行压缩,执行空间碎片整理,但是会引发STW)

G1(JDK11默认的垃圾回收器):将空间分为多个区域,为四种类型:Eden,Survivor,Old,Humongous(一种特殊的Old,专门放置大型对象),优先回收垃圾最多的区域(采用“Mark——Copy算法”,不会产生大量空间碎片)

13.JAVA中五种引用

强引用(最常见):不会被GC回收

软引用(SoftReference类实现):内存足够时不会被回收,内存不够时回收,适合用在内存敏感的应用中

弱引用(WeakReference类实现):GC回收一运行就会回收

虚引用(PhantomReference类实现):不能单独使用,跟踪对象被垃圾回收的状态

终结器引用:无需手动编码,内部配合引用队列使用,用以实现对象finalize()的方法


本文转载自: https://blog.csdn.net/qq_62585543/article/details/124916737
版权归原作者 社会的大D 所有, 如有侵权,请联系我们删除。

“JVM常问面试题(自答版)”的评论:

还没有评论