JVM口试真题总结(九)

打印 上一主题 下一主题

主题 552|帖子 552|积分 1656

文章收录在网站:http://hardyfish.top/
文章收录在网站:http://hardyfish.top/
文章收录在网站:http://hardyfish.top/
文章收录在网站:http://hardyfish.top/

形貌CMS垃圾网络的工作过程
   CMS(Concurrent Mark Sweep)垃圾网络器的工作过程
  重要可以分为以下四个阶段:
  初始标记(Initial Mark)
  

  • 这个阶段的目标是标记所有的 GC Roots 能直接关联到的对象。
  • 这个阶段需要停止所有的用户线程,但是一般情况下,这个阶段会很快完成。
  并发标记(Concurrent Mark)
  

  • 在这个阶段,垃圾网络器会遍历对象图,并标记所有的存活对象,从初始标记的对象开始。
  • 这个阶段是与用户线程并发实验的,不需要停止用户线程。
  重新标记(Remark)
  

  • 由于在并发标记阶段,用户线程还在运行,可能会修改了对象图,所以需要重新标记一次,以确保标记的准确性。
  • 这个阶段需要停止所有的用户线程。
  并发清除(Concurrent Sweep)
  

  • 在这个阶段,垃圾网络器会清除所有未被标记的对象。
  • 这个阶段是与用户线程并发实验的,不需要停止用户线程。
  如何防止内存走漏?
   防止内存走漏重要需要对代码进行精细的管理和控制,以下是一些常用的方法:
  及时开释对象:
  

  • 当对象不再使用时,及时将其引用设置为null,以便让垃圾接纳器可以或许接纳。
  使用弱引用(WeakReference):
  

  • 在Java中,使用WeakReference可以在不影响垃圾接纳器接纳对象的同时,还能使用到这个对象。
  • 当该对象只剩下弱引用时,垃圾接纳器会接纳它。
  制止使用静态变量:
  

  • 静态变量会在类加载时初始化,并在整个程序运行期间都存在,轻易造成内存走漏。
  • 假如非要使用,应确保在不需要时将其设置为null。
  及时关闭流、数据库毗连等资源:
  

  • 这些资源都是有限的,使用完后必须及时关闭,否则会造成资源走漏。
  使用finally块:
  

  • 在Java中,finally块始终会被实验,无论是否有异常发生。
  • 因此,可以在finally块中开释资源。
  制止在对象中保存过多的数据:
  

  • 假如一个对象保存了大量的数据,那么当这个对象被其他对象引用时,会消耗大量的内存。
  使用内存分析工具:
  

  • 内存分析工具(如MAT,VisualVM等)可以资助你找出内存走漏的泉源,从而更好地修复题目。
  对聚集类进行恰当的管理:
  

  • 对于聚集类,如List,Map等,应该制止让它们过大,并且在不再使用它们时,应该清空或者设置为null。
  留意线程的使用:
  

  • 假如线程对象得不到及时的烧毁,也会造成内存走漏。
  • 因此,对于线程对象,我们要特别警惕,确保其生命周期得到良好的管理。
  简述内存屏障及其类型
   内存屏障(Memory Barrier),也被称为内存栅栏,是一种处理器指令
  

  • 用于防止特定操作的重排序。
  它可以确保某些内存操作的顺序性,以及它们对其他处理器可见的顺序。
  内存屏障是处理器计划和多线程编程中的紧张概念
  

  • 它是实现诸如volatile,synchronized等高级同步构造的基础。
  内存屏障重要有以下四种类型:
  LoadLoad屏障:
  

  • 这种屏障确保了屏障之前的所有Load操作在屏障之后的Load操作之前完成。

    • 即不允许Load操作的重排序。

  StoreStore屏障:
  

  • 这种屏障确保了屏障之前的所有Store操作在屏障之后的Store操作之前完成。

    • 即不允许Store操作的重排序。

  LoadStore屏障:
  

  • 这种屏障确保了屏障之前的所有Load操作在屏障之后的Store操作之前完成。
  StoreLoad屏障:
  

  • 这种屏障确保了屏障之前的所有Store操作在屏障之后的Load操作之前完成。
  • 这是最强的一种内存屏障,也是开销最大的一种。
  在Java中,volatile关键字和synchronized关键字的实现就使用了内存屏障。
  例如,对volatile变量的写操作会插入StoreStore和StoreLoad屏障
  

  • 读操作会插入LoadLoad和LoadStore屏障。
  而synchronized关键字在锁定息争锁时也会插入相应的内存屏障,以确保操作的顺序性和可见性。
  哪些情况会导致栈内存溢出?
   栈内存溢出一般发生在递归调用且递归深度过深的场景。
  

  • 当一个线程请求的栈深度大于JVM所允许的深度,将抛出StackOverflowError异常。
  栈内存重要用于存储局部变量和实验动态链接,还用于方法调用和返回。
  

  • 每次方法调用都会创建一个新的栈帧,这个栈帧会被添加到线程的栈顶。
  • 假如这个方法调用其他方法,那么新的栈帧会继承被添加到栈顶。

    • 当方法调用完成,相应的栈帧会被弹出栈。

  每个线程都有一个私有的JVM栈,其大小可以固定也可以动态扩展。
  

  • 假如固定大小的栈满了,或者动态扩展的栈无法继承扩展,那么JVM就会抛出StackOverflowError。
  例如,假如你写了一个递归函数,没有提供恰当的递归出口,那么这个函数就会无限递归下去
  

  • 每次递归都会向栈添加一个新的栈帧,最终导致栈内存溢出。
  1. public void recursive() {
  2.     recursive();
  3. }
复制代码
以上面的代码为例,这个方法会不断地调用自己,每次调用都会创建一个新的栈帧并压入栈中
  

  • 但是没有任何方法可以弹出栈帧,因此最终会导致栈内存溢出。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

莫张周刘王

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

标签云

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