JVM常见面试题整理

  1. 请你谈谈你对JVM的理解?java8虚拟机有什么更新?

    参考文章:https://www.jianshu.com/p/7ae4447c58d4

    1. JVM是程序虚拟机,主要用于忽略操作系统之间的差异以在不同的操作系统上执行java程序,实现java程序的跨平台特性;
    2. JAVA 8对虚拟机的更新:不再有永久带这个概念,并且用元空间来代替原来的永久代。元空间中类及其相关的元数据和类加载器生命周期一致,每个类加载器有专门的存储空间,不会单独回收某个类,位置也是固定的,但是当类加载器不再存活时会把它相关的空间全部移除。
  2. 什么是OOM,请你说说OOM产生的原因?如何分析?

    1. OOM:当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时;
    2. OOM产生的原因:内存泄露、内存溢出
      1. 分配的少了
      2. 应用用的太多
    3. 分析OOM:
      1. java.lang.OutOfMemoryError: Java heap space
        • 产生原因:内存泄露或者堆的大小设置不当引起;
        • 解决办法:对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改;
      2. java.lang.OutOfMemoryError: PermGen space(即方法区溢出)
        • 产生原因:产生大量的Class信息存储于方法区(大量Class或者jsp页面,或者采用cglib等反射机制)或者过多的常量尤其是字符串也会导致方法区溢出;
        • 解决办法:可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改;
      3. java.lang.StackOverflowError:不会抛OOM error
        • 产生原因:程序中存在死循环或者深度递归调用或者栈大小设置太小
        • 解决办法:通过虚拟机参数-Xss来设置栈的大小
  3. JVM的常用调优参数有哪些?

    参考文章:https://www.koofun.com/pro/queanswers?proquestionId=1672

    1. -Xmx:指定java程序的最大堆内存, 使用java -Xmx5000M -version判断当前系统能分配的最大堆内存;
    2. -Xms指定最小堆内存, 通常设置成跟最大堆内存一样,减少GC
    3. -Xmn:设置年轻代大小。整个堆大小=年轻代大小 + 年老代大小。所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
    4. -Xss:指定线程的最大栈空间, 此参数决定了java函数调用的深度, 值越大调用深度越深, 若值太小则容易出栈溢出错误(StackOverflowError)
    5. -XX:PermSize:指定方法区(永久区)的初始值,默认是物理内存的1/64, 在Java8永久区移除, 代之的是元数据区, 由-XX:MetaspaceSize指定
    6. -XX:MaxPermSize:指定方法区的最大值, 默认是物理内存的1/4, 在java8中由-XX:MaxMetaspaceSize指定元数据区的大小
    7. -XX:NewRatio=n:年老代与年轻代的比值,-XX:NewRatio=2, 表示年老代与年轻代的比值为2:1
    8. -XX:SurvivorRatio=n:Eden区与Survivor区的大小比值,-XX:SurvivorRatio=8表示Eden区与Survivor区的大小比值是8:1:1,因为Survivor区有两个(from, to)
  4. 内存快照抓取,如何分析,命令是什么?

    1. jmap -dump:format=b,file=xxx.hprof 【pid可以通过jps获取】

    2. jmap -dump:format=b,live,file=xxx.hprof

    3. -XX:+HeapDumpOnOutOfMemoryError(在虚拟机出现OOM的时候自动生成dump文件)

    4. 分析内存快照:

      参考文章:https://blog.csdn.net/qq_42447950/article/details/81435080

      1. mat: eclipse memory analyzer, 基于eclipse RCP的内存分析工具。详细信息参见:http://www.eclipse.org/mat/,推荐使用。
      2. jhat:JDK自带的java heap analyze tool,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言OQL,分析相关的应用后,可以通过http://localhost:7000来访问分析结果。不推荐使用,因为在实际的排查过程中,一般是先在生产环境 dump出文件来,然后拉到自己的开发机器上分析,所以,不如采用高级的分析工具比如前面的mat来的高效。
    5. kill -3 杀一下jvm进程(错误的)

      1. kill -3是在目标Java进程的标准输出流上输出thread dump,也就是线程列表以及每个线程的stack trace。这个信号不用来做heap dump。

        kill的默认信号15(SIGTERM)也不会打heap dump。它会让Java进程执行关闭序列然后退出。关闭序列主要是shutdown hooks。

        kill -9(SIGKILL)则是直接把进程杀了,JVM来不及做任何事情就被干掉,所以也不会打heap dump。

  5. 堆里面分区:Eden、Survivor(from to)、老年区

    参考文章:https://blog.csdn.net/bright60/article/details/78930752

    1. JVM里面的堆内存空间,主要分为新生代空间和老年代空间,其中新生代空间分为两个部分(Egen区、Survivor区)和三个板块(1个Eden、两个Survivor);

    2. Eden区域是用来存放使用构造器创建的对象(new/newInstance),除非对象需要的空间超过了-XX:PretenureSizeThreshold,这样的对象会被直接放入老年代空间;

    3. 两个survivor区域,一般称为S0,S1:

      主要用于把Eden区域中活着的对象保存起来,而清空掉已经失活的对象;

      在一次Young GC中如果上一次存活的对象因为S0或者S1区域已满,而把对象放入old区域,但是这一次Young GC时该对象已经失活了,怎么处理呢?

    4. S0和S1的大小一般由以上两个参数来控制:

      1. -XX:SurvivorRatio = 8(是Eden和Survivor区域的比重,是一个Survivor的大小,如果将其设置为8,则说明Eden区域是一个Survivor的8倍)
      2. -XX:InitialSurvivorRatio = 8(是Young/S0,当其设置为8时,表示S0或S1占整个Young空间的12.5%);
      3. 在Young空间中的每个活着的对象,每次Minor GC都会在S0和S1之间转移,默认最多转移15次进入old空间,可以通过参数-XX:MaxTenuringThreshold = 15来设置
  6. GC垃圾收集算法有哪几个?谈谈利弊?

    参考文章:https://www.jianshu.com/p/4bdc443f5c92

    1. 引用计数法:为每个对象设置一个计数器,记录其被引用的次数,被其他对象引用时,计数器加1,该引用失效后计数器减一;计数器为0时表示不存在任何引用,在GC时被清除;(JVM一般不适用引用计数法GC)【每次引用生效和失效时进行加减法操作,判断计数器是否为0,如果为0则清除】
      1. 优点:
        • 思想和实现都比较简单(只需要为每一个对象配备一个计数器即可);
      2. 缺点:
        • 无法处理循环引用问题,可能会造成死锁(对象A和对象B相互引用,不存在其他对象引用A和B,此时A和B属于不可达对象,但是计数器无法识别这种垃圾对象之间的互相引用,从而引起内存泄露,不能够GC);
        • 计数器要求在每次引用生效和失效的时候进行加减法操作,在一定程度上影响系统性能。
    2. 标记清除法:标记所有的可达对象,则未标记的对象就是不存在引用的垃圾对象,GC时清除所有未标记的对象;【先标记再清除】
      1. 优点:
        • 只标记正常引用的对象,不标记循环引用这样的垃圾对象以及没有引用的对象,解决了循环引用的问题;
      2. 缺点:
        • 可能会产生空间碎片(不连续的内存空间),不连续的内存空间在内存分配时的工作效率低于连续的内存空间,尤其时堆大对象的内存分配;
    3. 复制算法:将内存空间分为两块相同的存储空间,每次只使用一块,GC时将正在使用的内存中的存活对象复制到另一块存储空间中,然后清除正在使用的空间的所有对象;【先复制再清除】
      1. 优点:
        • 存活对象相对少时,效率很高(需要复制的对象少),存活对象复制到另一空间时,解决了空间碎片的问题;
      2. 缺点
        • 系统内存只能使用一半的内存空间,而且如果存活对象过多时,比较耗时;
      3. 应用场景:java新生代串行垃圾回收器(优点:保证了内存空间的连续性,又避免了大量的空间浪费)
    4. 标记压缩法(标记清除压缩法):同标记清除算法一样首先标记存活的对象,但是再标记之后还要将所有标记的对象压缩到内存空间的一端后再清理边界外的所有空间;【标记+压缩+清除】
      1. 优点:
        • 解决了标记清除法带来的空间碎片问题,也不需要折损可使用空间;
      2. 缺点:压缩过程的处理提升了垃圾回收过程的复杂的?
      3. 应用场景:老年代的回收算法
    5. 分代算法:根据对象的特点堆内存空间进行划分,选择合适的垃圾回收算法。
      1. 优点:提交了垃圾回收的效率;
      2. 缺点:不同区域是使用不同的垃圾回收算法提升了垃圾回收过程的复杂度?
      3. 应用场景:虚拟机的垃圾回收器
    6. 分区算法:将整个堆空间划分为连续的不同小区间,每一个小区间都独立使用、独立回收
      1. 优点:可以控制一次回收多少个小区间,从而减少1GC的停顿时间;
      2. 缺点:
      3. 应用场景:
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值