JVM面试题

JVM面试题

  1. 什么情况下会发生栈内存溢出

    • 栈是线程私有的,每个方法在执行时都会创建一个栈帧,用来存储局部变量表、操作数栈、动态链接等信息。
    • 栈溢出一般有两种:StackOverFlowError 和 OutOfMemoryError
      • StackOverFlowError 多是因为 方法递归过深超过栈深度或者没有终止条件
      • OutOfMemoryError 多是线程启动过多导致
  2. JVM的内存结构,Eden和Survivor比例。

    • java 内存回收策略之一分代处理,在其 新生代 中划出几块区域 Eden 和 两块 survivor 区域,他们的分配比例默认是由JVM根据本地环境分配的:-XX:-UseAdaptiveSizePolic 。关闭该参数后比例为 8:1:1
  3. VM内存为什么要分成新生代,老年代,持久代。新生代中为什么要分为Eden和Survivor。

    • 分代个人认为主要为了避免全盘扫描,提升对象回收效率
    • 新生代分为Eden和Survivor,认为是为了进一步优化对象回收效率,新生代触发MinorGC后,活跃对象推送Survivor进一步去整理,可延迟发送到年老代,延缓年老代满触发FullGC,提升一定的性能。
  4. JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代,说说你知道的几种主要的JVM参数。

    • 对象在新生代中诞生->大对象直接进入老年代,小对象在触发minorGC过程中存入survivor两个区,待多次回收依然存活后进入老年代。
    • JVM参数:
      • -Xms128M:设置java程序启动时堆内存128M(默认为物理内存1/64,且小于1G)
      • -Xmx256M:设置最大堆内存256M,超出后会出现 OutOfMemoryError(默认为物理内存1/64,且小于1G)
      • -XX:NewRatio=2:设置年轻代与年老代的比例为2:1
      • -XX:+PrintGCDetails:打印GC信息
  5. 你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms和G1,包括原理,流程,优缺点。

    • Serial 串行收集器:单线程收集对象,暂停所有工作线程,直到完成。
    • ParNew收集器:Serial的多线程版本
    • CMS(Concurrent Mark Sweep)收集器:基于‘标记-清除’算法实现。针对年老代。
      • 初始标记-》并发标记-》重新标记-》并发清除
      • 1 无法处理在并发清除时产生的新垃圾 2 会有内存碎片产生
      • 优点:并发收集、短停顿时间
    • G1收集器:基于“标记整理”算法
      • 初始标记-》并发标记-》最终标记-》筛选回收
      • 不会产生内存碎片,有利于长时间运行、可预测的停顿时间、能独立管理整个GC堆(新生代和老年代)
  6. 垃圾回收算法的实现原理。

    • 标记-清除算法:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象
    • 复制算法:它将可用内存按容量划分大小相等的两块,用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
    • 标记-整理算法:标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存
    • 分代收集算法:Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法
  7. 当出现了内存溢出,你怎么排错。

    1. 首先确定内存溢出的区域,是堆内存还是栈溢出,即是OOM异常 还是 栈溢出,运行日志可判断出。
    2. 堆溢出说明GC有可能出现问题,有些对象没有及时回收,或在循环中创建对象等,可尝试打印堆日志。如果是栈溢出,可排查对吗中递归操作是够有条件退出,方法体是否有过大的循环调用。
  8. JVM内存模型的相关知识了解多少,比如重排序,内存屏障,happen-before,主内存,工作内存等。

    • java中实例对象、数组元素等都放在java堆中,java堆是线程共享的(主内存),每个线程有其私有线程(工作内存)。工作内存更新变量到主内存中: 工作内存执行store操作-》主内存执行write操作。工作内存从主内存中读取变量: 主内存执行read操作,将内存从主内存中读出来-》工作内存回字形load操作,将读出来的变量本地更新
    • 指令重排序:JVM 在保证程序的逻辑执行的前提下,会对一些代码的执行顺序做优化。volatile可防止指令重排序。
    • 内存屏障:禁止特定类型处理器的重排序,从而让程序按我们预想的流程去执行。内存屏障,又称内存栅栏,是一个CPU指令
    • happen-before : 多线程之间的操作关系,如果一个操作的执行结果需要另一个操作可见,那么他们之间存在happen-before关系。
  9. 简单说说你了解的类加载器,可以打破双亲委派么,怎么打破。

    • 类加载器 就是根据指定全限定名称将class文件加载到JVM内存,转为Class对象
    • 启动类加载器、其他类加载器、扩展类加载器、应用程序类加载器
    • 双亲委派模型工作过程是如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成
    • 打破双亲委派
      • java提供服务接口SPI,允许第三方实现,例如jdbc.
      • 打破双亲委派机制小重写loadClass和findClass方法
  10. 讲讲JAVA的反射机制。

    • 想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。
  11. 怎么打出线程栈信息。

    • 使用jstack pid 命令查看线程的堆栈信息。 通过jstack 命令可以获取当前进程的所有线程信息。 每个线程堆中信息中,都可以查看到线程ID、线程的状态(wait、sleep、running 等状态)、是否持有锁信息等。

      • jstack -l <pid> >jvm.txt
        
  12. 请解释如下jvm参数的含义:

    • -server -Xms512m -Xmx512m -Xss1024K
      • 设置堆内存512M,最大堆内存512M,线程栈大小1024K
    • -XX:PermSize=256m -XX:MaxPermSize=512m
      • 非堆区初始内存256M,其最大上限512M
    • -XX:MaxTenuringThreshold=20
      • 设置年龄阈值,被复制20次
    • -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSInitiatingOccupancyOnly
      • CMS在对内存占用率达到80%的时候开始GC
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值