垃圾收集器如何更新推入操作数堆栈的引用? [英] How does the Garbage Collector update the references pushed to the operand stack?

查看:76
本文介绍了垃圾收集器如何更新推入操作数堆栈的引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在堆中移动对象时,JVM可以轻松更新局部变量,静态引用,类实例或对象数组实例的引用.但是如何更新推入操作数堆栈的引用?

The JVM can easily update the references of local variables, static references, class instances or object array instances when moving an object in heap. But how can it update the references pushed to the operand stack?

推荐答案

局部变量与操作数堆栈中的条目之间没有根本区别.两者都生活在同一个堆栈框架中.两者均未正式声明,并且都需要JVM进行推理以识别其实际用途.

There is no fundamental difference between a local variable and an entry in the operand stack. Both live in the same stack frame. Neither is formally declared and both need the JVM to perform inference to recognize their actual use.

以下代码

public static void example() {
    {
        int foo = 42;
    }
    {
        Object bar = "text";
    }
    {
        long x = 100L;
    }
    {
        Object foo, bar = new Object();
    }
}

(通常)将被编译为

  public static void example();
    Code:
       0: bipush        42
       2: istore_0
       3: ldc           #1                  // String text
       5: astore_0
       6: ldc2_w        #2                  // long 100l
       9: lstore_0
      10: new           #4                  // class java/lang/Object
      13: dup
      14: invokespecial #5                  // Method java/lang/Object."<init>":()V
      17: astore_1
      18: return

请注意如何使用不同类型的值重新分配堆栈帧中位于索引0的局部变量.另外,最后存储到变量索引1会使索引0处的变量无效,否则它将包含long值的一半悬挂.

Note how the local variable at index 0 in the stack frame gets reassigned with values of different types. As a bonus, the last store to variable index 1 invalidates the variable at index 0 as it otherwise would contain a dangling half of a long value.

没有关于局部变量类型的其他提示,调试信息是可选的,并且堆栈映射表仅在代码包含分支时才存在.

There are no additional hints about the type of local variables, debugging information is optional and stack map tables are only there when the code contains branches.

确定局部变量是否包含引用的唯一方法是遵循程序流程并追溯指令的效果.这确实意味着要推断操作数堆栈上的值,因为没有它,我们甚至都不知道store指令放入变量中的内容.

The only way to determine whether a local variable contains a reference, is to follow the program flow and retrace the effect of the instructions. This does already imply inferring the values on the operand stack, as without it, we wouldn’t even know what the store instruction put into the variable.

验证程序可以做到这一点,甚至是强制性的,垃圾收集器或JVM的任何支持代码也可以做到.一个实现甚至可能只有一个分析代码,其中保留了第一个分析的类型信息,这将是验证.

The verifier does it, it’s even mandatory, and the garbage collector or whatever supporting code of the JVM can do it too. An implementation may even have a single analyzing code keeping the type information of the first analysis, which would be the verification.

但是,即使每次垃圾收集器都需要重建此信息时,开销也不会是天文数字.垃圾收集器仅定期运行,并且仅需要当前执行的方法的此信息.而这仅是解释执行.

But even when this information is reconstructed every time the garbage collector needs it, the overhead would not be astronomical. The garbage collector runs only periodically and it only needs this information for the currently executed methods. And that’s all about interpreted execution only.

JIT编译器生成代码时,无论如何都需要利用类型信息,并且可以为垃圾收集器准备信息,但是仅对某些称为 safepoints 的点(生成的代码会对其进行检查)进行处理是否有出色的垃圾收集.这意味着在这些点之间,数据不必采用垃圾收集器能够理解的形式,并且优化的代码可以假定垃圾收集器在处理对象时不会重定位对象.

When the JIT compiler generates code, it needs to utilize the type information anyway and can prepare information for the garbage collector, but it will do so only for certain points called safepoints where the generated code checks whether there’s an outstanding garbage collection. This implies that in-between these points, the data doesn’t need to be in a form the garbage collector understands and the optimized code may assume that the garbage collector won’t relocate objects while it is processing them.

这还意味着在经过编译的,优化的代码中,可达性可能与简单的解释执行中的完全不同,即,可能不存在未使用的变量,但是即使从源代码的角度来看,使用中的对象也可能被视为未经过优化的代码.代码使用其字段的副本,例如在CPU寄存器中.

It also implies that in compiled, optimized code the reachability might be entirely different than in simple interpreted execution, i.e. unused variables might be absent, but even objects in use from a source code point of view may be considered unused when the optimized code works with copies of their fields, e.g. in CPU registers.

这篇关于垃圾收集器如何更新推入操作数堆栈的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆