栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

实际上,JVM如何收集SoftReferences?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

实际上,JVM如何收集SoftReferences?

看起来它可能是可调的,但事实并非如此。并发标记清除收集器挂在默认堆的实现上,

must_clear_all_soft_refs()
该堆显然仅
true
在执行时才执行
_last_ditch_collection

bool GenCollectedHeap::must_clear_all_soft_refs() {  return _gc_cause == GCCause::_last_ditch_collection;}

虽然正常处理失败的分配具有对堆

do_collect
方法的三个连续调用,但在
CollectorPolicy.cpp

HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size,        bool   is_tlab) {

尝试收集,尝试重新分配,如果失败,则尝试扩展堆,然后作为最后的努力,尝试收集清除软引用。

对最后一个集合的评论很有说服力(也是唯一一个触发清除软引用的评论)

  // If we reach this point, we're really out of memory. Try every trick  // we can to reclaim memory. Force collection of soft references. Force  // a complete compaction of the heap. Any additional methods for finding  // free memory should be here, especially if they are expensive. If this  // attempt fails, an OOM exception will be thrown.  {    IntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted    gch->do_collection(true  , true  , size  , is_tlab          , number_of_generations() - 1 );  }

-–为回应显而易见的内容而编辑,我描述的是弱引用,而不是软引用-

在实践中,我可以想象当调用JVM进行垃圾回收以响应它们试图避免时,SoftReferences只会被“不”跟随

OutOfMemoryError

为了使

SoftReference
s与所有四个Java
1.4垃圾收集器以及新的G1收集器兼容,决策必须仅取决于可到达性确定。到收割和压实发生时,确定某个对象是否可触​​及为时已晚。这表明(但不要求)存在一个集合“上下文”,该集合根据堆中的可用内存可用性确定可达性。这样的上下文必须
SoftReference
在尝试关注之前指示不关注。

由于

OutOfMemoryError
回避垃圾收集是按全收集的“停止世界”的方式专门安排的,因此很难想象堆管理器
SoftReference
在收集发生之前设置“不遵循”标志的情况。

-–好的,所以我认为“必须以这种方式工作”的答案还不够好-

从源代码src / share / vm / gc_implementation / concurrentMarkSweep /
vmCMSOperations.cpp
(突出显示是我的)

实际“执行”垃圾收集的操作:

  170 void VM_GenCollectFullConcurrent::doit() {

我们最好成为VM线程,否则“程序”线程就是垃圾回收!

  171   assert(Thread::current()->is_VM_thread(), "Should be VM thread");

我们是并发收集器,因此最好同时进行调度!

  172   assert(GCLockerInvokesConcurrent || ExplicitGCInvokesConcurrent, "Unexpected");  173

抓取堆(其中具有GCCause对象)。

  174   GenCollectedHeap* gch = GenCollectedHeap::heap();

检查是否需要前台“年轻”集合

  175   if (_gc_count_before == gch->total_collections()) {  176     // The "full" of do_full_collection call below "forces"  177     // a collection; the second arg, 0, below ensures that  178     // only the young gen is collected. XXX In the future,  179     // we'll probably need to have something in this interface  180     // to say do this only if we are sure we will not bail  181     // out to a full collection in this attempt, but that's  182     // for the future.

程序线程是否不干预堆?

  183     assert(SafepointSynchronize::is_at_safepoint(),  184       "We can only be executing this arm of if at a safepoint");

从堆中获取垃圾回收原因(此回收的原因)。

  185     GCCauseSetter gccs(gch, _gc_cause);

充分收集年轻空间

请注意,他传递了堆的must_clear_all_soft_refs标志的值,该标志在OutOfMemory场景中必须已设置为true,并且无论哪种情况,都将“
do_full_collection”定向为不遵循软引用

  186     gch->do_full_collection(gch->must_clear_all_soft_refs(),  187       0 );

_gc_cause是一个枚举,

_allocation_failure
在第一次尝试中将其设置为(guesswork)以避免
OutOfMemoryError
_last_ditch_collection
然后失败(尝试收集临时垃圾)

快速浏览一下内存“堆”模块,发现

do_full_collection
其中的
do_collection
软引用的调用已使用行显式清除(在“正确”条件下)

  480   ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy());

-–那些想要学习弱引用的人的原始帖子如下-

在标记和清除算法中,主线程 不会 遵循软引用(因此不会进行标记,除非其他分支可以通过非软引用到达软引用)。

在复制算法中,对象软引用指向的对象 不会被 复制(同样,除非其他非软引用到达了它们)。

基本上,从“主”执行线程中遵循引用Web时, 遵循软引用。这允许对它们的对象进行垃圾回收,就像它们没有指向它们的引用一样。

重要的是要提到,软引用几乎 永远不会
孤立地使用。它们通常用于设计要对该对象有多个引用的对象中,但是只需要清除一个引用即可触发垃圾回收(为便于维护容器或无需查找昂贵的引用的运行时性能) 。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/596047.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号