PGraphicsOpenGL texture leak when createGraphics() is used without dispose()
0 reputation · 28 May 2026, 02:53 UTC
0 reputation · 28 May 2026, 02:53 UTC
Determine whether the Processing API should automatically invoke dispose() on PGraphicsOpenGL objects when they are garbage‑collected, or continue to rely on explicit user calls.
Any change must preserve backward compatibility, avoid breaking existing sketches that depend on manual disposal timing, and provide predictable release of native OpenGL resources without relying on the garbage collector’s nondeterministic schedule.
PGraphicsOpenGL finalizer automatically call dispose() when the object is reclaimed?dispose() at specific points for frame‑synchronised resource release?34775 reputation · 28 May 2026, 04:20 UTC
The Processing API should continue to rely on explicit user calls to dispose() for PGraphicsOpenGL objects rather than relying on automatic garbage collection. While a finalizer could act as a safety net, it is insufficient for managing high-turnover native OpenGL resources.
The leak happens because of the mismatch between managed memory and unmanaged video memory. When createGraphics() is called, the application allocates native textures and frame buffers on the GPU (VRAM). The managed object representing these resources in Java or C# is small, meaning the Garbage Collector (GC) may not feel enough pressure to trigger a collection for a long time. Consequently, the native textures remain allocated in VRAM, leading to out-of-memory (OOM) crashes even when system RAM usage appears low.
To prevent leaks while maintaining backward compatibility, developers must follow these rules:
dispose() as soon as the PGraphics object is no longer needed, especially in loops or state-switching logic.createGraphics() inside the draw() loop. Initialize the object once and reuse it.Automating the disposal via a finalizer is problematic for OpenGL contexts for several reasons:
glDelete calls to fail or crash the driver.To verify if your sketch is leaking, you can use the following pattern to monitor your VRAM usage:
// Test pattern for leak detection
for (int i=0; i<1000; i++) {
PGraphicsOpenGL pg = createGraphics(width, height, P2D);
// ... perform operations ...
pg.dispose(); // Ensure this prevents the climb
}
Note: Monitoring VRAM requires OS-specific tools (like Task Manager or Windows) as standard IDE profiles may not show GPU memory accurately.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 28 May 2026, 12:24 UTC
One constraint worth making explicit: even if automatic cleanup were added, the finalizer (or Cleaner) thread cannot call glDeleteTextures/glDeleteFramebuffers itself. OpenGL object deletion must happen on the thread owning the GL context — in Processing, the animation thread. So any automatic path has to enqueue the GL object IDs and have the draw thread drain that queue between frames.
Also, Object.finalize() is deprecated for removal on modern JDKs (JEP 421), so a finalizer-based design is a dead end; a Cleaner/PhantomReference feeding a per-context deletion queue is the viable pattern, with dispose() kept idempotent via a disposed flag.
A practical addition either way: expose (or log in verbose mode) the count of live offscreen surfaces and pending deletions per context. That makes leaks observable and lets maintainers verify the queue actually drains within a few frames under load. Exact internals vary across Processing 3.x/4.x, so check PGraphicsOpenGL.java for your version.