Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以从gc角度将java对象标记为不可收集以节省gc扫描时间?_Java_Garbage Collection - Fatal编程技术网

是否可以从gc角度将java对象标记为不可收集以节省gc扫描时间?

是否可以从gc角度将java对象标记为不可收集以节省gc扫描时间?,java,garbage-collection,Java,Garbage Collection,是否可以从gc角度将java对象标记为不可收集以节省gc扫描时间 类似的东西,特别是非垃圾收集容器(非垃圾收集?) 问题是,我有很多普通的临时对象,但我有更大的(几gig)对象,它们是为了缓存而存储的。Java GC不应该无缘无故地遍历所有这些缓存千兆字节,试图找到任何要收集的内容,因为它们包含有自己超时的缓存数据 通过这种方式,我可以以一种定制的方式将数据划分为无限生命对象和正常生命对象,并且希望GC能够非常快,因为正常对象的生命不会太长,数量也会更小 对于这个问题,有一些解决办法,比如商业化

是否可以从gc角度将java对象标记为不可收集以节省gc扫描时间

类似的东西,特别是非垃圾收集容器(非垃圾收集?)

问题是,我有很多普通的临时对象,但我有更大的(几gig)对象,它们是为了缓存而存储的。Java GC不应该无缘无故地遍历所有这些缓存千兆字节,试图找到任何要收集的内容,因为它们包含有自己超时的缓存数据

通过这种方式,我可以以一种定制的方式将数据划分为无限生命对象和正常生命对象,并且希望GC能够非常快,因为正常对象的生命不会太长,数量也会更小


对于这个问题,有一些解决办法,比如商业化的Terracotta BigMemory(http://terracotta.org/products/bigmemory),但java本机解决方案会更好(我是说免费的,可能更可靠?)。我还希望避免序列化开销,这意味着它应该发生在同一个jvm中。据我所知,DirectMemory和BigMemory主要在堆外运行,这意味着对象必须在jvm之外的内存中序列化/反序列化。简单地在jvm中标记非gc区域似乎是一个更好的解决方案。使用文件进行缓存也不是一个选项,它具有同样难以承受的序列化/反序列化开销-用例是一个HA服务器,它以随机(人工)顺序使用大量数据,并且需要低延迟。

JVM管理的任何内存也由JVM进行垃圾收集。而任何直接可用于Java方法而无需反序列化的“活动”对象都必须存在于JVM内存中。因此,在我的理解中,你不能拥有对垃圾收集免疫的活动对象

另一方面,您描述的用法应该使垃圾收集的分代方法非常有效。如果您的大型对象在周围停留一段时间,则会较少检查它们的回收情况。因此,我怀疑避免这些检查能带来多少好处

是否可以从gc角度将java对象标记为不可收集以节省gc扫描时间

不,这是不可能的

您可以通过保持对象的可访问性来防止对象被垃圾收集,但是GC仍然需要跟踪它们以检查每个完整对象的可访问性;GC(至少)


这只是我的假设,当jvm饥饿时,它也开始扫描所有那些不必要的对象


对。这是正确的。然而,除非您有很多对象希望以这种方式处理,否则开销可能是微不足道的。(无论如何,更好的办法是给JVM更多的内存…如果可能的话。)

非常简单,要做到这一点,垃圾收集算法需要知道这样一个标志,并在工作时考虑它

我不知道任何标准的GC算法都有这样一个标志,因此为了使它起作用,您需要编写自己的GC算法(在决定某种可行的方式将此信息传达给它之后)

原则上,事实上,您已经开始这样做了——您正在决定如何进行垃圾收集,而不是乐于将垃圾收集留给JVM的GC算法。你描述的情况对你来说是一个可测量的问题;现有的垃圾收集还不够,但是您的计划可以工作吗?垃圾收集器的调优非常好,所以如果“低效”的默认策略实际上比您天真的最佳策略更快,我也不会感到惊讶


(在最好的情况下,进行手动内存管理是很棘手的,而且容易出错;在使用库存垃圾收集器处理剩余内存的同时,自己管理一些内存似乎更糟。我预计您会遇到很多边缘情况,其中GC假定它“知道”整个堆发生了什么,这将不再是真的。如果可以避免…

建议使用商业RTSJ实现来避免GC,或者使用堆外内存。人们还可以研究缓存的软引用(它们确实会被收集)

不建议这样做: 如果出于某种原因,您认为这些选项不够,您可以研究不安全的直接内存访问(sun.misc.UNSAFE的一部分)。您可以使用“theUnsafe”字段获取“Unsafe”实例。不安全允许通过“allocateMemory”和“freeMemory”分配/取消分配内存。这不受GC控制,也不受JVM堆大小的限制。一旦您走上这条路线,对GC/应用程序的影响就无法保证——这就是为什么使用字节缓冲区可能是一条出路(如果您没有使用类似RTSJ的实现)


希望这有帮助

活Java对象将始终是GC生命周期的一部分。或者换一种方式说,将对象标记为非gc与将对象由根引用(例如静态最终映射)引用的开销顺序相同

但再进一步考虑,放在缓存中的数据很可能是临时的,最终会被逐出。此时,您将再次开始喜欢JVM和GC。 如果您有100 GB的永久数据,您可能需要重新考虑应用程序的体系结构,并尝试共享和分发数据(水平可伸缩性)

最后但并非最不重要的一点是,围绕序列化做了大量工作,而序列化的开销(我不是说ObjectInputStream和ObjectOutputStream名声不佳)并没有那么大。 此外,如果您的数据主要由基元类型(包括字节数组)组成,那么有一种从堆外缓冲区(例如Instance)读取int()或readBytes()的有效方法。这可能是一种解决问题的方法