This is an automated email from the ASF dual-hosted git repository. reta pushed a commit to branch 3.6.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 0fb8e21a6ae4ea6fb8353d689a8e6a05757f78f0 Author: Peter Palaga <[email protected]> AuthorDate: Wed Nov 5 21:58:50 2025 +0100 GraalVM detects a started Thread in the image heap after fixing CXF-9171 (#2706) (cherry picked from commit 0e63a3954bd6080c08c0cb7791523a0b49a721d0) (cherry picked from commit ab8dc1eb08fc077a873c17f12557b3ba211cf684) --- .../cxf/io/DelayedCachedOutputStreamCleaner.java | 36 ++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/org/apache/cxf/io/DelayedCachedOutputStreamCleaner.java b/core/src/main/java/org/apache/cxf/io/DelayedCachedOutputStreamCleaner.java index d3e33be785..0d9caea829 100644 --- a/core/src/main/java/org/apache/cxf/io/DelayedCachedOutputStreamCleaner.java +++ b/core/src/main/java/org/apache/cxf/io/DelayedCachedOutputStreamCleaner.java @@ -80,7 +80,8 @@ public final class DelayedCachedOutputStreamCleaner implements CachedOutputStrea } private static final class SingleTimerDelayedCleaner implements DelayedCleaner { - private static final Timer TIMER = new Timer("DelayedCachedOutputStreamCleaner", true); + private static volatile Timer timer; + private static final Object TIMER_LOCK = new Object(); private final long delay; /* default is 30 minutes, in milliseconds */ private final DelayQueue<DelayedCloseable> queue = new DelayQueue<>(); @@ -109,7 +110,18 @@ public final class DelayedCachedOutputStreamCleaner implements CachedOutputStrea } if (newTimerTask != null) { - TIMER.scheduleAtFixedRate(newTimerTask, 0, Math.max(MIN_DELAY, delay >> 1)); + Timer t; + // CHECKSTYLE:OFF + // May the Gods of Code Style forgive us these three inner assignments + if ((t = timer) == null) { + synchronized (TIMER_LOCK) { + if ((t = timer) == null) { + t = timer = new Timer("DelayedCachedOutputStreamCleaner", true); + } + } + } + // CHECKSTYLE:ON + t.scheduleAtFixedRate(newTimerTask, 0, Math.max(MIN_DELAY, delay >> 1)); } } @@ -269,7 +281,7 @@ public final class DelayedCachedOutputStreamCleaner implements CachedOutputStrea private static final class DelayedCloseable implements Delayed { private final Closeable closeable; private final long expireAt; - + DelayedCloseable(final Closeable closeable, final long delay) { this.closeable = closeable; this.expireAt = System.nanoTime() + TimeUnit.NANOSECONDS.convert(delay, TimeUnit.MILLISECONDS); @@ -295,15 +307,15 @@ public final class DelayedCachedOutputStreamCleaner implements CachedOutputStrea if (this == obj) { return true; } - + if (obj == null) { return false; } - + if (getClass() != obj.getClass()) { return false; } - + final DelayedCloseable other = (DelayedCloseable) obj; return Objects.equals(closeable, other.closeable); } @@ -326,8 +338,8 @@ public final class DelayedCachedOutputStreamCleaner implements CachedOutputStrea } else if (SINGLE_TIMER_STRATEGY.equalsIgnoreCase(strategy)) { delayedCleanerStrategy = SingleTimerDelayedCleaner::new; } else { - throw new IllegalArgumentException("The value of " + CachedConstants.CLEANER_STRATEGY_BUS_PROP - + " property is invalid: " + strategy + " (should be " + DEFAULT_STRATEGY + " or " + throw new IllegalArgumentException("The value of " + CachedConstants.CLEANER_STRATEGY_BUS_PROP + + " property is invalid: " + strategy + " (should be " + DEFAULT_STRATEGY + " or " + SINGLE_TIMER_STRATEGY); } } @@ -352,7 +364,7 @@ public final class DelayedCachedOutputStreamCleaner implements CachedOutputStrea } else { cleaner = NOOP_CLEANER; if (value != 0) { - throw new IllegalArgumentException("The value of " + CachedConstants.CLEANER_DELAY_BUS_PROP + throw new IllegalArgumentException("The value of " + CachedConstants.CLEANER_DELAY_BUS_PROP + " property is invalid: " + value + " (should be >= " + MIN_DELAY + ", 0 to deactivate)"); } } @@ -382,11 +394,11 @@ public final class DelayedCachedOutputStreamCleaner implements CachedOutputStrea public void clean() { cleaner.clean(); } - + @Override public void initComplete() { } - + @Override public void postShutdown() { // If cleanup on shutdown is asked, force cleaning all cached output streams @@ -395,7 +407,7 @@ public final class DelayedCachedOutputStreamCleaner implements CachedOutputStrea cleaner.close(); } } - + @Override public void preShutdown() { // If cleanup on shutdown is asked, defer closing till postShutdown hook
