From fcb3a065304479c449bc1bcf0fde29f031cd5589 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=8A?=
=?UTF-8?q?=D1=80=20=D0=9A=D1=83=D1=80=D1=82=D0=B0=D0=BA=D0=BE=D0=B2?=
Date: Tue, 23 Dec 2025 11:45:32 +0200
Subject: [PATCH] Stop dealing with ThreadDeath
Java 20+ Thread.stop throws UnsupportedOperationException and thus
ThreadDeath is not thrown by anything anymore. Stop dealing with it.
https://inside.java/2022/11/09/quality-heads-up/
---
.../workbench/swt/IEventLoopAdvisor.java | 33 +++++++++----------
.../workbench/swt/PartRenderingEngine.java | 8 +----
.../eclipse/jface/operation/ModalContext.java | 20 ++---------
.../src/org/eclipse/jface/window/Window.java | 7 +---
.../ui/application/WorkbenchAdvisor.java | 4 +--
.../eclipse/ui/internal/ExceptionHandler.java | 10 ++----
.../workbench/PartRenderingEngineTests.java | 6 ----
7 files changed, 24 insertions(+), 64 deletions(-)
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/IEventLoopAdvisor.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/IEventLoopAdvisor.java
index 5c1d6577b9d..7f18033c0cf 100644
--- a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/IEventLoopAdvisor.java
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/IEventLoopAdvisor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2015 IBM Corporation and others.
+ * Copyright (c) 2011, 2025 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -39,27 +39,26 @@ public interface IEventLoopAdvisor {
public void eventLoopIdle(Display display);
/**
- * Performs arbitrary actions when the event loop crashes (the code that
- * handles a UI event throws an exception that is not caught).
+ * Performs arbitrary actions when the event loop crashes (the code that handles
+ * a UI event throws an exception that is not caught).
*
- * This method is called when the code handling a UI event throws an
- * exception. In a perfectly functioning application, this method would
- * never be called. In practice, it comes into play when there are bugs in
- * the code that trigger unchecked runtime exceptions. It is also activated
- * when the system runs short of memory, etc. Fatal errors (ThreadDeath) are
- * not passed on to this method, as there is nothing that could be done.
+ * This method is called when the code handling a UI event throws an exception.
+ * In a perfectly functioning application, this method would never be called. In
+ * practice, it comes into play when there are bugs in the code that trigger
+ * unchecked runtime exceptions. It is also activated when the system runs short
+ * of memory, etc. Fatal errors are not passed on to this method, as there is
+ * nothing that could be done.
*
*
- * Clients must not call this method directly (although super calls are
- * okay). The default implementation logs the problem so that it does not go
- * unnoticed. Subclasses may override or extend this method. It is generally
- * a bad idea to override with an empty method, and you should be especially
- * careful when handling Errors.
+ * Clients must not call this method directly (although super calls are okay).
+ * The default implementation logs the problem so that it does not go unnoticed.
+ * Subclasses may override or extend this method. It is generally a bad idea to
+ * override with an empty method, and you should be especially careful when
+ * handling Errors.
*
*
- * @param exception
- * the uncaught exception that was thrown inside the UI event
- * loop
+ * @param exception the uncaught exception that was thrown inside the UI event
+ * loop
*/
public void eventLoopException(Throwable exception);
}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java
index cfcd37e51d0..f69766adcf0 100644
--- a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2019 IBM Corporation and others.
+ * Copyright (c) 2008, 2025 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -1151,8 +1151,6 @@ public void eventLoopException(Throwable exception) {
}
advisor.eventLoopIdle(display);
}
- } catch (ThreadDeath th) {
- throw th;
} catch (Exception | Error err) {
handle(err, advisor);
}
@@ -1166,10 +1164,6 @@ private void handle(Throwable ex, IEventLoopAdvisor advisor) {
try {
advisor.eventLoopException(ex);
} catch (Throwable t) {
- if (t instanceof ThreadDeath) {
- throw (ThreadDeath) t;
- }
-
// couldn't handle the exception, print to console
t.printStackTrace();
}
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/operation/ModalContext.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/operation/ModalContext.java
index 7a8e2fb5244..e790734796e 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/operation/ModalContext.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/operation/ModalContext.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2025 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -122,10 +122,6 @@ public void run() {
if (runnable != null) {
runnable.run(progressMonitor);
}
- } catch (ThreadDeath e) {
- // Make sure to propagate ThreadDeath, or threads will never
- // fully terminate.
- throw e;
} catch (InvocationTargetException | InterruptedException | RuntimeException | Error e) {
throwable = e;
} finally {
@@ -170,12 +166,6 @@ public void block() {
}
exceptionCount = 0;
}
- // ThreadDeath is a normal error when the thread is dying.
- // We must propagate it in order for it to properly
- // terminate.
- catch (ThreadDeath e) {
- throw (e);
- }
// For all other exceptions, log the problem.
catch (Throwable t) {
if (t instanceof VirtualMachineError) {
@@ -414,10 +404,6 @@ public static void run(IRunnableWithProgress operation, boolean fork,
static Throwable invokeThreadListener(IThreadListener listener, Thread switchingThread) {
try {
listener.threadChange(switchingThread);
- } catch (ThreadDeath e) {
- // Make sure to propagate ThreadDeath, or threads will never
- // fully terminate
- throw e;
} catch (RuntimeException | Error e) {
return e;
}
@@ -438,9 +424,7 @@ private static void runInCurrentThread(IRunnableWithProgress runnable, IProgress
InterruptedException interruptedException = new InterruptedException(e.getLocalizedMessage());
interruptedException.initCause(e);
throw interruptedException;
- } catch (InvocationTargetException | InterruptedException | ThreadDeath e) {
- // Make sure to propagate ThreadDeath, or threads will never fully
- // terminate.
+ } catch (InvocationTargetException | InterruptedException e) {
throw e;
} catch (RuntimeException | Error e) {
throw new InvocationTargetException(e);
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/window/Window.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/window/Window.java
index 0b9c5aa68d9..444b0c1dab5 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/window/Window.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/window/Window.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2025 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -129,11 +129,6 @@ public static interface IExceptionHandler {
private static class DefaultExceptionHandler implements IExceptionHandler {
@Override
public void handleException(Throwable t) {
- if (t instanceof ThreadDeath) {
- // Don't catch ThreadDeath as this is a normal occurrence when
- // the thread dies
- throw (ThreadDeath) t;
- }
// Try to keep running.
t.printStackTrace();
}
diff --git a/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/application/WorkbenchAdvisor.java b/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/application/WorkbenchAdvisor.java
index 441bc25deaf..294f3b727e3 100644
--- a/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/application/WorkbenchAdvisor.java
+++ b/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/application/WorkbenchAdvisor.java
@@ -280,8 +280,8 @@ public void postShutdown() {
* In a perfectly functioning application, this method would never be called. In
* practice, it comes into play when there are bugs in the code that trigger
* unchecked runtime exceptions. It is also activated when the system runs short
- * of memory, etc. Fatal errors (ThreadDeath) are not passed on to this method,
- * as there is nothing that could be done.
+ * of memory, etc. Fatal errors are not passed on to this method, as there is
+ * nothing that could be done.
*
*
* Clients must not call this method directly (although super calls are okay).
diff --git a/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/ExceptionHandler.java b/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/ExceptionHandler.java
index 965d4a82284..703f7d6a189 100644
--- a/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/ExceptionHandler.java
+++ b/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/ExceptionHandler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2025 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -17,8 +17,7 @@
/**
* This handler will pass along to the workbench advisor exceptions and errors
- * thrown while running the event loop. However, the ThreadDeath
- * error is simply thrown again, and is not passed along.
+ * thrown while running the event loop.
*/
public final class ExceptionHandler implements Window.IExceptionHandler {
@@ -42,11 +41,6 @@ private ExceptionHandler() {
@Override
public void handleException(Throwable t) {
try {
- // Ignore ThreadDeath error as its normal to get this when thread dies
- if (t instanceof ThreadDeath) {
- throw (ThreadDeath) t;
- }
-
// Check to avoid recursive errors
exceptionCount++;
if (exceptionCount > 2) {
diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/PartRenderingEngineTests.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/PartRenderingEngineTests.java
index 892e40a2c11..f22fb36b344 100644
--- a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/PartRenderingEngineTests.java
+++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/PartRenderingEngineTests.java
@@ -151,12 +151,6 @@ private void handle(Throwable ex, IEventLoopAdvisor advisor) {
try {
advisor.eventLoopException(ex);
} catch (Throwable t) {
- // The type ThreadDeath has been deprecated since version 20
- // and marked for removal
- if ("ThreadDeath".equals(t.getClass().getSimpleName())) {
- // don't catch ThreadDeath by accident
- throw t;
- }
// couldn't handle the exception, print to console
t.printStackTrace();
} finally {