From c0d2a25c2cd402eaac2bfd37ac143c5d575b371f Mon Sep 17 00:00:00 2001 From: arunjose696 Date: Thu, 9 Oct 2025 15:24:21 +0200 Subject: [PATCH] Fix memory-leak in FigureUtilities by disposing GC on font change Before this change figureUtilities created a GC once for an application and then reused it to calculate font/text dimensions. Due to the recent modification of GC in SWT to store Operations, every operation on FigureUtilities that sets the font on the GC (i.e., that calls setFont()) creates a SetFontOperation in the GC. Since that GC is never disposed, these operation accumulate throughout the application lifecycle and constituted a memory leak The current change addresses this issue by instead of crearting a single GC we create a single shell for the lifetime of the application. Whenever a different font needs to be set, the old GC is properly disposed and replaced with a new one created from the shell. This ensures that no GC objects persist indefinitely, effectively preventing the memory leak. --- .../org/eclipse/draw2d/FigureUtilities.java | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureUtilities.java b/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureUtilities.java index f677db53d..ee0da87ff 100644 --- a/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureUtilities.java +++ b/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureUtilities.java @@ -32,6 +32,7 @@ public class FigureUtilities { private static final float RGB_VALUE_MULTIPLIER = 0.6f; private static GC gc; + private static Shell shell; private static Font appliedFont; private static FontMetrics metrics; private static Color ghostFillColor = new Color(null, 31, 31, 31); @@ -59,7 +60,7 @@ public static Color darker(Color color) { public static FontMetrics getFontMetrics(Font f) { setFont(f); if (metrics == null) { - metrics = getGC().getFontMetrics(); + metrics = gc.getFontMetrics(); } return metrics; } @@ -74,14 +75,20 @@ public static FontMetrics getFontMetrics(Font f) { @Deprecated protected static GC getGC() { if (gc == null) { - Shell shell = new Shell(); + gc = new GC(getShell()); + appliedFont = gc.getFont(); + } + return gc; + } + + private static Shell getShell() { + if (shell == null) { + shell = new Shell(); InternalDraw2dUtils.configureForAutoscalingMode(shell, event -> { // ignored }); - gc = new GC(shell); - appliedFont = gc.getFont(); } - return gc; + return shell; } /** @@ -95,7 +102,7 @@ protected static GC getGC() { */ protected static org.eclipse.swt.graphics.Point getTextDimension(String s, Font f) { setFont(f); - return getGC().textExtent(s); + return gc.textExtent(s); } /** @@ -123,7 +130,7 @@ public static IFigure getRoot(IFigure figure) { */ protected static org.eclipse.swt.graphics.Point getStringDimension(String s, Font f) { setFont(f); - return getGC().stringExtent(s); + return gc.stringExtent(s); } /** @@ -341,10 +348,14 @@ public static void paintEtchedBorder(Graphics g, Rectangle r) { * @since 2.0 */ protected static void setFont(Font f) { - if (appliedFont == f || (f != null && f.equals(appliedFont))) { + if ((appliedFont == null && f == null && gc != null) || (f != null && f.equals(appliedFont))) { return; } - getGC().setFont(f); + if (gc != null && !gc.isDisposed()) { + gc.dispose(); + } + gc = new GC(getShell()); + gc.setFont(f); appliedFont = f; metrics = null; }