【问题标题】:Lambda expression anonymous object life cycleLambda 表达式匿名对象生命周期
【发布时间】:2014-11-01 07:01:39
【问题描述】:

我的问题是关于 JVM 1.8 中匿名对象的处理和生命周期。

据我所知,在 JDK 1.8 中,lambda 表达式的底层机制并不是纯粹基于函数的。 IE。它仍然使用我们在代码中定义的方法创建一个匿名对象,并在匿名对象上调用该方法。另外,由于 lambda 表达式没有引入任何新的变量作用域,因此在 lambda 表达式中调用“this”将引用原始对象而不是此类匿名方法。

问题自然就来了:JVM 是如何处理这种匿名对象的生命周期的?将包含此类lambda表达式的对象方法定义为“外部对象方法”,至少我有以下问题。

  1. 如果外部对象方法是普通方法,这个匿名对象是属于实例级别还是类级别?如果外部方法是静态的呢?

  2. 如果外部对象方法被多次调用,这个匿名对象会被重用还是重新创建?

  3. 此类对象是否受 JVM GC 约束?如果是,GC 规则是否与其他对象相同?

  4. 鉴于无法在代码中直接引用,是否有任何工具或 API 可以跟踪此类匿名对象的生命周期?

感谢任何帮助、评论或文档。

【问题讨论】:

  • 1) 和 2) 或多或少取决于 JVM 的实现,尽管 HotSpot 在这些方面非常聪明。 3)是的,像往常一样。 4) 你可以正常追踪它;如果需要,您可以将其直接分配给功能接口类型并正常跟踪它。
  • 谢谢。如果我们在某个地方有一些正式的文档会很好。对于通过 yes 的对象,它肯定是可跟踪的;但我想知道是否嵌入了这样的对象。它可能应该是相同的机制,但你知道,有时会有例外。
  • 我有一个关于这个匿名对象生命周期的类似问题,如果我把创建 lambda 表达式放在一个循环中,Java Runtime 会创建这个匿名对象的多个实例。

标签: java object lambda garbage-collection lifecycle


【解决方案1】:
  1. 我不知道你所说的“属于”是什么意思。对象不“属于”任何级别。

  2. 如果 lambda 是一个闭包,即如果它从周围范围捕获一个或多个局部变量(包括 this(有点像隐式 final 局部变量)、OuterClass.this(隐式访问)通过this 的隐藏字段),或不合格的实例变量(通过thisOuterClass.this 隐式访问),然后在不同的时间计算包含lambda 表达式的函数,它可能必须创建不同的对象,因为捕获的变量的值存储为 lambda 对象的一部分,并且由于在函数的不同运行中(甚至在函数的一次运行中的不同时间),捕获的变量可以具有不同的值,不同的 lambda 对象必须创建,以便每个 lambda 记住其单独的一组捕获值。

    但是,如果 lambda 不是闭包,则从该 lambda 表达式创建的任何两个 lambda 对象在语义上都无法区分。因此,一个对象可以重新用于该 lambda 表达式的所有评估。我相信在这种情况下,虚拟机将为该 lambda 静态分配一个对象,该对象会在程序运行期间存在。

  3. 是的。如果在运行 lambda 表达式时创建了一个对象,那么它会像 Java 中的其他对象一样被动态分配,并且会受到 GC 的影响。但是,如果在程序的整个生命周期中都创建了一个对象(参见上面 (2) 的讨论),那么它就不是内存管理的,类似于字符串文字。

【讨论】:

  • 谢谢,但您的回答只是猜测。如果您有任何官方文档来确认 JVM 的行为,或者至少是 Oracle JVM,那就太好了。当然,JVM“可以”重用它并且“可以”GC这些匿名对象;但我要问的是它是否“确实”重复使用或 GC 它们。
猜你喜欢
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 2019-06-01
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
相关资源
最近更新 更多