JVM相干面试题

打印 上一主题 下一主题

主题 574|帖子 574|积分 1722

  1. 1. 类加载与双亲委派机制
  2. 聊一下你对类加载器的理解。
  3. 类加载器是JVM用来加载类文件到内存的组件。它负责将字节码文件解析为java.lang.Class实例,并存储到运行时数据区的方法区中。类加载器分为Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader,它们共同构成了类加载的层次结构。
  4. 2.双亲委派机制是什么?它的作用是什么?
  5. 双亲委派机制是指当一个类加载器加载类时,它会先将请求委派给父加载器,只有当父加载器无法加载时,才会尝试自己加载。它的作用是避免类的重复加载,确保类的唯一性,并防止用户自定义类覆盖核心类库。
  6. 3.JVM中类加载器的种类有哪些?
  7. Bootstrap ClassLoader:加载JVM核心类库(如rt.jar),由C++实现。
  8. Extension ClassLoader:加载扩展类库(如jre/lib/ext目录下的类)。
  9. Application ClassLoader:加载应用类路径(classpath)中的类。
  10. Custom ClassLoader:用户自定义类加载器,通过继承ClassLoader实现。
  11. 如何自定义类加载器?
  12. 自定义类加载器需要继承ClassLoader类,并重写findClass(String name)方法。通常还需要实现loadClass方法来实现双亲委派机制。
  13. 示例代码:
  14. java
  15. 复制
  16. public class MyClassLoader extends ClassLoader {
  17.     @Override
  18.     protected Class<?> findClass(String name) throws ClassNotFoundException {
  19.         byte[] classData = loadClassData(name);
  20.         if (classData == null) {
  21.             throw new ClassNotFoundException();
  22.         }
  23.         return defineClass(name, classData, 0, classData.length);
  24.     }
  25.     private byte[] loadClassData(String name) {
  26.         // 加载类文件的字节码
  27.         // 示例:从文件系统加载
  28.         try {
  29.             String fileName = name.replace('.', File.separatorChar) + ".class";
  30.             InputStream in = new FileInputStream(fileName);
  31.             ByteArrayOutputStream out = new ByteArrayOutputStream();
  32.             int b;
  33.             while ((b = in.read()) != -1) {
  34.                 out.write(b);
  35.             }
  36.             return out.toByteArray();
  37.         } catch (IOException e) {
  38.             e.printStackTrace();
  39.         }
  40.         return null;
  41.     }
  42. }
  43. 自定义类加载器时需要注意哪些问题?
  44. 确保遵循双亲委派机制,避免类的重复加载。
  45. 注意线程安全问题。
  46. 确保加载的字节码符合JVM规范。
  47. 避免内存泄漏。
  48. 4. JVM运行时数据区
  49. JVM运行时数据区有哪些部分组成?
  50. 堆(Heap):存储对象实例和数组。
  51. 方法区(Method Area):存储类的结构信息,如常量池、字段、方法等。
  52. Java栈(Java Stack):存储局部变量、操作数栈和方法调用信息。
  53. 本地方法栈(Native Method Stack):支持本地方法的执行。
  54. 程序计数器(Program Counter Register):记录当前线程执行的字节码指令地址。
  55. 5.Java堆(Heap)的作用是什么?为什么需要分代设计?
  56. 作用:堆是JVM管理内存的主要区域,用于存储对象实例和数组。
  57. 分代设计:为了提高垃圾回收效率,堆被分为年轻代和老年代。年轻代存储新创建的对象,老年代存储经过多次回收仍然存活的对象。分代设计可以针对不同类型的对象采用不同的回收策略,提高回收效率。
  58. 方法区、元空间和持久代的关系是什么?
  59. 方法区:JVM规范中定义的区域,用于存储类的结构信息。
  60. 持久代(Permanent Generation):JDK 1.7及之前的实现,方法区的物理实现。
  61. 元空间(Metaspace):JDK 1.8引入的替代持久代的区域,使用本地内存,避免了持久代的内存溢出问题。
  62. J
  63. 6.Java栈和本地方法栈的区别是什么?
  64. Java栈:用于存储Java方法的调用信息,如局部变量表、操作数栈等。
  65. 本地方法栈:用于支持本地方法(如JNI调用)的执行,存储本地方法的调用信息。
  66. 程序计数器的作用是什么?
  67. 程序计数器记录当前线程执行的字节码指令地址。如果当前线程正在执行Java方法,则记录字节码指令的地址;如果正在执行本地方法,则为undefined。程序计数器是线程私有的,每个线程都有自己的程序计数器。
  68. 7. 栈帧结构与动态链接
  69. 栈帧的结构是怎样的?
  70. 栈帧是方法调用的内存模型,每个方法调用都会创建一个新的栈帧。栈帧结构包括:
  71. 局部变量表:存储方法参数和局部变量。
  72. 操作数栈:用于存储操作数和中间结果。
  73. 动态链接:将常量池中的符号引用转换为直接引用。
  74. 方法出口信息:记录方法返回地址等信息。
  75. 8.动态链接的作用是什么?
  76. 动态链接是指在运行时将常量池中的符号引用转换为直接引用。它允许在运行时解析类、方法和字段的引用,从而支持多态和动态绑定。
  77. 9.如何理解局部变量表和操作数栈?
  78. 局部变量表:存储方法参数和局部变量,每个变量占用一个槽(slot)。局部变量表的大小在编译时确定。
  79. 操作数栈:用于存储操作数和中间结果。操作数栈的大小也在编译时确定。操作数栈支持栈操作,如压栈(push)和弹栈(pop)。
  80. 10. 垃圾回收机制
  81. 垃圾回收的触发条件是什么?
  82. 堆内存不足:当堆内存无法分配新对象时,触发垃圾回收。
  83. Eden区满:在分代收集中,当Eden区满时,触发Minor GC。
  84. 老年代内存不足:当老年代内存不足时,触发Full GC。
  85. 元空间不足:当元空间内存不足时,也可能触发垃圾回收。
  86. 11.常见的垃圾回收算法有哪些?
  87. 标记-清除算法:标记活动对象,清除未标记的对象。缺点是会产生内存碎片。
  88. 标记-整理算法:标记活动对象,并将活动对象移动到内存的一端,整理内存空间。
  89. 复制算法:将内存分为两块,每次只使用一块,当一块内存用满时,将活动对象复制到另一块内存中。
  90. 标记-清除算法和标记-整理算法的区别是什么?
  91. 标记-清除算法:标记活动对象,清除未标记的对象。优点是简单,缺点是会产生内存碎片。
  92. 标记-整理算法:标记活动对象,并将活动对象移动到内存的一端,整理内存空间。优点是减少内存碎片,缺点是需要移动对象,可能导致性能开销。
  93. 分代收集算法的工作原理是什么?
  94. 分代收集算法将堆分为年轻代和老年代。年轻代使用复制算法,老年代使用标记-整理算法或标记-清除算法。年轻代的垃圾回收称为Minor GC,老年代的垃圾回收称为Full GC。
  95. 12.常见的垃圾收集器有哪些?它们的优缺点是什么?
  96. Serial收集器:单线程收集器,适合单核处理器。优点是简单高效,缺点是会暂停所有线程(Stop-The-World)。
  97. Parallel收集器:多线程收集器,适合多核处理器。优点是吞吐量高,缺点是会暂停所有线程。
  98. CMS收集器:并发标记-清除收集器,适合低延迟场景。优点是并发执行,减少停顿时间,缺点是会产生内存碎片。
  99. G1收集器:分区收集器,适合大堆内存。优点是分区收集,减少停顿时间,缺点是配置复杂。
  100. ZGC:低延迟垃圾收集器,适合超大堆内存。优点是低延迟,缺点是资源消耗较高。
  101. 13.如何选择合适的垃圾收集器?
  102. 根据应用的场景选择垃圾收集器:
  103. 如果应用对延迟要求不高,可以选择吞吐量优先的收集器(如Parallel收集器)。
  104. 如果应用对延迟要求高,可以选择低延迟的收集器(如CMS收集器或G1收集器)。
  105. 如果堆内存较大,可以选择分区收集器(如G1收集器或ZGC)。
  106. 14.G1垃圾收集器的工作原理是什么?如何调优?
  107. 工作原理:G1收集器将堆内存划分为多个大小相等的区域(Region),分为Eden区、Survivor区和老年代区。G1通过并发标记和分区收集的方式,减少停顿时间。
  108. 调优:
  109. 使用-XX:G1HeapRegionSize设置区域大小。
  110. 使用-XX:MaxGCPauseMillis设置最大停顿时间目标。
  111. 使用-XX:G1NewSizePercent和-XX:G1MaxNewSizePercent调整新生代大小。
  112. 15.ZGC的特点是什么?
  113. 低延迟:ZGC的目标是将停顿时间控制在10ms以内。
  114. 高吞吐量:支持大堆内存(如TB级)。
  115. 并发执行:大部分垃圾回收工作与应用线程并发执行。
  116. 如何判断是否适用G1垃圾收集器?
  117. 应用堆内存较大(如大于4GB)。
  118. 应用对延迟要求较高。
  119. 应用的新生代和老年代对象比例差异较大。
  120. 16. JVM性能优化
  121. JVM性能优化的常用方法有哪些?
  122. 调整堆大小:根据应用需求调整堆大小(-Xms和-Xmx)。
  123. 选择合适的垃圾收集器:根据应用需求选择合适的垃圾收集器。
  124. 调整垃圾收集器参数:根据应用需求调整垃圾收集器参数(如-XX:MaxGCPauseMillis)。
  125. 减少内存泄漏:通过工具(如JProfiler、VisualVM)检测和修复内存泄漏。
  126. 优化代码:减少不必要的对象创建和大对象分配。
  127. 17.如何分析JVM的性能问题?
  128. 使用JVM监控工具(如VisualVM、JProfiler)监控JVM的性能指标,如堆内存使用情况、垃圾回收频率、线程状态等。
  129. 使用jstack、jmap、jstat等命令行工具分析线程堆栈、堆内存和垃圾回收情况。
  130. 分析GC日志,了解垃圾回收的频率和停顿时间。
  131. 18.JVM常用命令有哪些?它们的作用是什么?
  132. jps:列出当前Java进程。
  133. jstack:打印线程堆栈信息,用于分析线程状态和死锁问题。
  134. jmap:生成堆转储文件,用于分析内存泄漏和内存使用情况。
  135. jstat:监控垃圾回收情况,如Eden区、Survivor区和老年代的使用情况。
  136. jcmd:发送命令到Java进程,如触发GC、生成堆转储文件等。
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

梦应逍遥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表