面试题-jvm

面试题

jvm

栈的常见问题
  1. 栈溢出的情况

    栈溢出:StackOverflowError

    举个简单的例子:在main方法中调用main方法,就会不断压栈执行,直到栈溢出;栈的大小可以固定,也可以动态变化。如果固定可以用-Xss设置栈的大小;如果动态变化,当栈大小,到达,内存空间不足,就会抛出OutOfMemory异常。

  2. 调整栈大小,就能保证不出现溢出吗?

    不能,因为调整栈大小,只会减少出现溢出的可能,栈大小不是无限扩大的,所以不能保证不出现溢出。

  3. 分配的栈内存越大越好吗?

    不是,因为增加栈大小,会造成每个线程的栈都变得很大,使得一定的栈空间下,能创建的线程数量会变小。

  4. 垃圾回收是否会涉及虚拟机栈?

    不会,垃圾回收只会涉及到方法区和堆中,方法区和堆也会存在溢出的可能;程序计数器只记录运行下一行的地址,不存在溢出和垃圾回收;虚拟机栈和本地方法栈,都是只涉及压栈和出栈,可能存在栈溢出,不存在垃圾回收。

程序计数器
  1. 为了保证程序连续执行下去,cpu必须采取某些手段来确定下一条指令的地址。程序计数器正是起到了这种作用,通常又称为指令计数器
  2. 在程序开始执行前,必须将它的起始地址,即程序的指令的内存单元地址送入PC,因此程序计数器内容是从内存提取的第一条指令的地址。当执行指令时,cpu将自动修改程序计数器的内容,即每执行一条指令程序计数器增加一个量,这个量等于指令所含的字节数以便保持将要执行的下一条指令的地址。
  3. 由于大多数指令都是按照顺序来执行的,所有修改的过程通常只是简单的对pc加1
  4. 当程序转移时,转移指令执行的最终结果就是要改变pc值,来实现转移。
本地方法栈

简单来说,一个本地方法就是一个java调用非java代码接口,一个本地方法是一个java方法:该方法的实现由非java语言实现,比如c.

  • java虚拟机用于管理java方法的调用,而本地方法栈用于管理本地方法的调用。
  • 本地方法栈,也是线程私有的
  • 允许被实现固定或者是可动态扩展的内存大小
  • 本地方法是使用c语言实现的
方法区

在这里插入图片描述
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

jdk7方法区称为永久代,jdk8,使用元空间取代永久代

元空间与永久代最大的区别在于:元空间不在虚拟机设置内存中,而是使用本地内存

方法区中放什么?

类型信息,字段信息、方法信息、常量池、静态常量等。

分代?

java堆区分为年轻代和老年代

年轻代又可以分为eden空间、survivor0空间和survivor1空间

在这里插入图片描述
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 几乎所有的java对象都是在eden区被new出来的
  • 绝大部分的java对象的销毁都在新生代进行。
如何设置新生代和老年代比例?

默认:新生代占1,老年代占2

可以使用选项-Xmn设置新生代最大内存大小

如何设置Eden、幸存者区比例?

eden空间和另外两个survivor空间缺省所占比例是8:1:1

可以用-XX:SurvivorRatio调整这个空间比例。

对象内存分配

在这里插入图片描述
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对象栈上分配

我们通过jvm内存分配可以知道java中的对象都是在堆上进行分配,当对象没有被引用的时候,需要依靠GC进行回收内存,如果对象数量较多的时候,会给GC带来较大压力,也间接影响了应用的性能。为了减少临时对象在堆内分配的数量,jvm通过逃逸分析确定该对象不会被外部访问。如果不会被外部访问,在栈上分配内存,这样该对象所占用的内存空间就可以随栈帧而销毁,就减轻了垃圾回收的压力。

对象逃逸分析:就是分析对象动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用,jvm对于这种情况可以通过开启逃逸分析参数来优化对象内存分配位置,使其通过标量替换优先分配在栈上,jdk7之后默认开启逃逸分析,

结论:栈上分配依赖于逃逸分析和标量替换

对象在eden区分配

大多数情况下,对象在新生代中eden区分配。

大对象直接进入老年代

为什么呢?为了避免为大对象分配内存时的复制操作而降低效率

长期存活的对象将进入老年代

当它的年龄增加到一定程度(默认15岁,cms收集器默认6岁,不同的垃圾收集器会略微有点不同),就会被晋升到老年代中。

老年代空间分配担保机制

年轻代每次minor gc 之前jvm都会计算下老年代剩余可用空间,

如果这个可用空间小于年轻代里面所有对象大小之和

就会看一个-XX:-HandlePromotionFailure的参数是否设置了

如果有这个参数,就会看看老年代的可用内存大小,是否大于之前每一层minor gc后进入老年代的对象平均大小。

如果小于或者没有参数设置,那么就会触发一次Full gc ,老年代和年代代一起回收一次垃圾,如果回收完还是没有足够空间存放新的对象就会发生OOM

当然,如果minor gc之后剩余存活的需要挪动到老年代的对象大小还是大于老年代可以空间,那么也会触发full gc,如果还是没有空间,则会发生oom

在这里插入图片描述
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对象内存回收
可达性分析算法

将GC Root对象作为起点,从这些节点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未标记的对象都是垃圾对象。

常用引用类型

java的引用类型一般分为四种:强引用、软引用、弱引用、虚引用

强引用:内存空间不够的时候,不会回收

软引用:正确情况不会被回收,内存空间不够的时候,会回收

弱引用:遇见gc就会回收

虚引用:回收机制和弱引用差不多,但是它被回收之前,会被放入ReferenceQueue中。

finalize()方法最终判定对象是否存活

即使在可达性分析算法中不可达的对象,也并非是“非死不可”的,这时候他们暂时处于缓刑阶段,要真正宣布一个对象死亡,至少要经历再次标记过程。

  1. 第一次标记并进行一次筛选

    筛选条件此对象是否有必要执行finalize()方法,没有覆盖finalize()方法,将直接被回收。

  2. 第二次标记

    如果覆盖了finalize()方法,对象还有一次存活的机会,如果对象要在finalize中拯救自己,只要重新与引用链上的对象关联。否则被回收

如何判断一个类是无用的类?

无用类需要满足3个条件:

  • 该类所有的对象实例都已经被回收,也就是java堆中不存在该类的任何实例
  • 加载该类的ClassLoader已经被回收
  • 该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。
垃圾收集算法及垃圾收集器
垃圾收集算法

在这里插入图片描述
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

分代收集理论

根据对象存活周期的不同将内存分为几块,一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。

标记-复制算法

缺点:在对象存活率较高时就要进行较多的复制工作,效率变低

​ 对空间浪费,因为复制至少需要2块相同内存,但是每次只用一块

标记-清除算法

缺点:效率问题(如果需要标记的对象太多,效率不高)

	 空间问题(标记清除后会产生大量不连续的碎片)
标记-整理算法

标记过程,然后让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。

垃圾收集器

如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现

serial收集器

最基本,历史最悠久的垃圾收集器。是一个单线程,只会使用一条垃圾收集线程去完成垃圾收集工作,重要但是他在垃圾收集工作的时候必须暂停其他所有的工作线程,直到它收集结束。

Parallel Scavenge 收集器

Parallel收集器其实就是Serial收集器的多线程版本。除了使用多线程进行垃圾收集外,其余行为和Serial收集器类似。

ParNew收集器

ParNew收集器其实跟Parallel收集器类似,区别主要在于它可以和CMS收集器配合使用。

CMS收集器

是一种以获取最短回收停顿时间为目标的收集器。它非常符合用户体验在应用上使用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程同时工作。

cms收集器是一种标记-清除算法实现的,整个过程分为四个步骤:

初始标记->并发标记->重新标记->并发清理->并发重置

el收集器类似,区别主要在于它可以和CMS收集器配合使用。

CMS收集器

是一种以获取最短回收停顿时间为目标的收集器。它非常符合用户体验在应用上使用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程同时工作。

cms收集器是一种标记-清除算法实现的,整个过程分为四个步骤:

初始标记->并发标记->重新标记->并发清理->并发重置

  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值