ToB企服应用市场:ToB评测及商务社交产业平台
标题:
JVM口试真题总结(九)
[打印本页]
作者:
莫张周刘王
时间:
3 天前
标题:
JVM口试真题总结(九)
文章收录在网站: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。
例如,假如你写了一个递归函数,没有提供恰当的递归出口,那么这个函数就会无限递归下去
每次递归都会向栈添加一个新的栈帧,最终导致栈内存溢出。
public void recursive() {
recursive();
}
复制代码
以上面的代码为例,这个方法会不断地调用自己,每次调用都会创建一个新的栈帧并压入栈中
但是没有任何方法可以弹出栈帧,因此最终会导致栈内存溢出。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4