如果确保在收集时调用finalize(),年轻一代还能获得速度优势吗?

为什么年轻一代的垃圾收集速度很快取决于一个事实:年轻一代中的大多数对象很快就会死亡。因此,当发生了年轻一代的收集时,很少有仍然存在的对象被移到旧一代中,从那时起,年轻一代中的所有数据都可以被认为是无用的(部分或它们被移动了,重置无法到达),并且这无需进一步扫描即可重新使用存储和平。在这种情况下,无法扫描无法到达的对象,可以节省大量时间。

但是我有一个问题,在Java中有一种方法finalize()(尽管在Java 9中已弃用),如果收集器保证会调用finalize(),则它需要扫描无法访问的对象,不只是通过生物,速度优势似乎消失了。

所以

  1. 我是对的吗? (finalize()使年轻一代的收藏大为增加 速度变慢,速度优势消失了。)
  2. 如果没有,JVM如何处理此问题? (例如,忽略 finalize()?)
  3. 除了上述问题,年轻一代还有其他 优势?

编辑: 我正在为具有finalize()功能的语言编写gc,在这种情况下我无法快速进行收集。

maomaoaijie 回答:如果确保在收集时调用finalize(),年轻一代还能获得速度优势吗?

基本上,您做对了。但是,幸存者对象不会立即复制到上一代。取而代之的是,将它们复制到Survivor空间中,在那里必须生存一定数量的可配置垃圾回收,然后才能升级到老一代。

但是基本假设是正确的。如果对象的生存期超过必要时间,并且不得不调用FROM openjdk:8-jre-slim WORKDIR /app RUN \ apt-get update -qq && apt-get install -y -qq curl && \ curl -sSL https://github.com/containous/traefik/releases/download/v2.0.4/traefik_v2.0.4_linux_amd64.tar.gz | tar -xz COPY bin/myapp.sh . COPY target/universal/bluevalet-server.zip . COPY deploy/traefik/traefik.toml . COPY deploy/traefik/metrics.toml . COPY deploy/nginx.conf . COPY deploy/run.sh . #run.sh ~~> ./traefik --configfile /app/traefik.toml & ./myapp.sh CMD [ "/app/run.sh" ] EXPOSE 9000 EXPOSE 9100 会延长对象的生存期,则会降低效率。

根本的解决方法是使这种情况例外。这个问题甚至在the specification中得到解决:

  

为了提高效率,实现可能会跟踪那些不会覆盖Object类的finalize方法或以平凡的方式覆盖它的类。

     

例如:

finalize()
     

我们鼓励实现将此类对象视为具有未覆盖的终结器,并更有效地完成它们,如§12.6.1中所述。

对于HotSpot JVM,它可以识别protected void finalize() throws Throwable { super.finalize(); } 继承的方法何时未被覆盖,或者何时被空方法覆盖。 Afaik,并非总是能够识别出唯一的超级呼叫,但是对于您自己的语言,可能可以识别出来。

因此,对于Java中的大多数对象,Object无需调用,因为它无论如何都不会生效,也不会被调用。解决了延长寿命的问题,因为它现在仅适用于少数几个对象。

通过使用仅为那些具有简单平凡化处理程序的对象创建的特殊参考对象,消除了对死对象进行扫描的需要,而该对象本身始终可以访问。因此,仍然只有那些需要扫描的对象。可以在this answer中找到更多详细信息。

本文链接:https://www.f2er.com/3146509.html

大家都在问