Skip to content

GC live lock #10652

@filipnavara

Description

@filipnavara

Android framework version

net9.0-android, net10.0-android (Preview)

Affected platform version

.NET 9, .NET 10

Description

We have an application that sometimes ends up in a vicious GC cycle live lock. The bug happens when the app goes through rapid UI section switching which results in a large number of Java proxy objects being allocated in a short time. What happens next is the following:

  • GRef exhaustion: The number of Java Global References (GRefs) exceeds 90% of the system threshold (approximately > 46,800). Every subsequent GRef allocation (essentially any access to Java objects) triggers a Full GC.
  • Full GC triggers a relatively expensive GC Bridge, where garbage collection is synchronized across both .NET and Java. This involves complex logic to reconcile references from one managed heap to the other; roughly 22k objects (give or take) enter this process.
  • The GC bridge clears almost nothing, so the GRef count remains critical. The system gets stuck in a loop of constant garbage collection.
  • Finalizer Bottleneck: The lack of memory recovery is partly because Java objects have finalizers, all of which run on the Finalizer Thread.
  • The Finalizer Thread is preoccupied because every Full GC triggers a Gen2GcCallback, which runs trimming of various ArrayPool<T>.Shared array pools.

This creates a vicious cycle from which the application cannot recover.

Steps to Reproduce

See above. We don't have repro app but we do have GC dumps and sampling profiler traces from the app.

Did you find any workaround?

No, but I believe it may potentially help to call GC.WaitForPendingFinalizers() before GC.Collect() when the GRef threshold is reached here:

Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageIssues that need to be assigned.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions