0

假设我们采用如下示例代码

class Employee 
{
    int id;
    String name;
}

Employee e = new Employee(1, "NewEmployee");

在上面的代码中,我假设首先为 Employee Object 分配堆内存,然后将其引用分配给堆栈引用e

以上是有效的还是这里发生了一些深层次的事情?

如果是,那么让我们假设在堆中的内存创建之后并且就在其引用分配给之前e,GC 启动并确定没有来自 GC 根的对该新堆内存的引用。

  1. GC 会清理这个资源吗?
  2. JVM/CLR 有没有办法处理这些场景并避免这种内存损坏?

标记 Java 和 C#,因为我看到 Java 和 C# 的标记和扫描情况下的清理逻辑似乎几乎相同(至少在从根中识别未使用的对象和清理方面)。

4

1 回答 1

3

然后让我们假设在堆中创建内存之后,就在它的引用被分配给 e 之前,GC 启动并确定没有来自 GC 根的对这个新堆内存的引用

这是错误的假设,GC 根本不会在这样的分配中间起作用。显然,这将是不正确和危险的行为。

更一般地说,当 JITtting 方法时,“安全点”被注入到 GC 可能启动的地方。这些通常是子方法调用、长循环等(它严格依赖于 JIT 实现)。

不确定 JVM,但在 CLR 的情况下,即使您将获取生成的汇编代码(例如使用https://sharplab.io),也很难看到有关安全点的“GCInfo” 。我不知道除 WinDbg 之外的任何工具可以看到它。

于 2019-04-17T08:52:44.217 回答