|
1
3
看来,Kotlins
在Java中编写
该消息仍将被打印,因为方法接收器,
因此,字节码看起来像
第一条指令推送
之后,堆栈包含的旧值
Kotlin生成的字节码不同:
当构造函数调用接收到另一个新构建的对象(指令12-20)时,您的用例会更加复杂,但我们可以忽略这一点,而专注于其他方面。
引用的第一条指令(第8条)是在阅读
按照要求的顺序提供这些参考资料
只抓了一个。现在,变量#2包含对对象的引用,字节码既没有作用域,也没有变量删除操作。引用将保留在局部变量中,直到该变量被覆盖用于其他目的或方法返回为止。当我们浏览剩余的代码时,我们看到在这个特定的设置中,变量#2不会再次使用,因此,当代码调用
如中所述 Can java finalize an object when it is still in scope? 被本地变量引用并不能阻止垃圾回收本身。从形式上讲,当对象没有被使用超过该点时,它仍然有资格进行垃圾回收。但在实践中是否会收集垃圾,取决于方法的优化状态。因此,当这段代码在您的场景中可重复地防止垃圾收集时,就不足为奇了。
如果Kotlin支持使用
无论出于何种原因,指令27和28都将常数0存储在从未使用过的变量#3中。这不会影响其余代码的行为。 |
|
|
2
0
(Meta:回答我自己的问题,不是为了减少公认的答案,而是为了添加一些信息,这些信息可能对那些碰巧遇到类似问题并最终阅读本文的人有用。) 原因 Kotlin编译器似乎有时会在引擎盖下引入局部变量来存储函数使用的各种值,原因对开发人员来说可能并不明显(事实上,我不知道它为什么这么做;如果有人知道添加答案或注释会很酷的话)。一旦从局部变量引用了一个对象,尽管理论上在最后一次使用该变量后仍然可以对其进行垃圾收集,但在实践中似乎没有(至少在某些设置中,可能不是所有设置都看到 this question 例如)。 诊断
诊断这种情况的一种方法是查看生成的Java字节码,例如使用
字节码将显示
例如,在问题中发布的字节码的以下摘录中:
人们可以看到
什么时候发生的? 如上所述,我真的不知道Kotlin编译器为什么会这样做。我也远不知道发生这种情况时的所有情况。但我确实注意到了两个不同的情况(一个来自问题中的最小示例,另一个来自我的实际用例):
将表达式传递给时
构造阵列时:
这就是在我的实际用例中发生的情况。我正在将一个特别构建的数组传递给一个函数(通过
如果有人在类似的情况下读到它有类似的问题,这可能是原因。可能还有其他情况。任何知道的人都欢迎回答/评论/编辑。当然,您可以通过查看上面解释的字节码来诊断问题,无论您的案例是否在这里列出。 救济 我设法想出了三种不同的方法来应对这种情况:
|
|
codeforester · 测量GC暂停时间的最佳方法是什么? 8 年前 |
|
|
Venki WAR · 需要解释G1的并行完整GC 8 年前 |
|
|
Stephan_Berlin · 为什么CMS系列中的初始标记阶段 8 年前 |
|
|
Bonsaisteak · 为什么年轻一代需要三个区域来收集垃圾? 8 年前 |
|
|
goks · 如何清除熊猫的数据帧内存? 8 年前 |