Skip to content

Redline: native resources of an unclosed Instance are never released (no Cleaner fallback) #203

Description

@andreaTP

A native Instance that is dropped without close() leaks all of its off-heap resources: the executable code region (~8 MB for a QuickJS-sized module), trampolines, jffi closures / Panama upcall stubs, ctx and args buffers, the tables and the linear memory. Nothing is registered with a java.lang.ref.Cleaner, so GC never reclaims them, unlike a bytecode instance where everything lives on the heap.

Measured with quickjs4j on Endive 1.1.0 (javy module, jffi runner, JDK 21): creating and dropping an engine without closing its instance grows RSS by ~30 MB per instance, linearly (1 GB after 20). With Instance.close() it saturates after JIT warm-up (~1 MB per instance residual over 50 instances, worth a look but minor).

quickjs4j had exactly this bug (Engine.close() never closed the Instance, which was harmless on bytecode) and other embedders will too. Suggested:

  • register the native machine and memory with a Cleaner as a fallback, so an unreachable instance releases its native resources on GC;
  • document in the redline docs that native instances must be closed, since the bytecode fallback never required it.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions