From b3d0f4451fcf3f61d0dd5b0f3a39015314bb0969 Mon Sep 17 00:00:00 2001 From: Valera V Harseko Date: Wed, 8 Jul 2026 17:18:41 +0300 Subject: [PATCH] Launch AdminUI helper threads outside the constructor (CodeQL java/thread-start-in-constructor) The AdminUI() constructor started two threads - one that builds the Swing frame (joined before the constructor returned) and one that resolves the local host name - so both anonymous Thread subclasses captured `this` and could touch AdminUI fields before construction had finished (a hazard in particular if the class were subclassed). Move that block into a new public launch() method and have main() call it right after constructing the instance, before connect(). AdminUI is only ever created by its own main(), and the collaborator classes merely hold a reference passed to their setup() methods, so no other caller is affected. The main() flow is unchanged: construct (records the RMI host) -> launch (builds the frame, waits for it, starts the host-name lookup) -> connect. The frame is still fully built before connect() runs. --- .../main/java/com/persistit/ui/AdminUI.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/persistit/ui/src/main/java/com/persistit/ui/AdminUI.java b/persistit/ui/src/main/java/com/persistit/ui/AdminUI.java index 5a47719ae6..b8175c9341 100644 --- a/persistit/ui/src/main/java/com/persistit/ui/AdminUI.java +++ b/persistit/ui/src/main/java/com/persistit/ui/AdminUI.java @@ -12,6 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. + * Portions Copyrighted 2026 3A Systems, LLC */ package com.persistit.ui; @@ -202,11 +203,20 @@ public AdminUI(final Management management) { public AdminUI(final String rmiHost) { this(); _rmiHost = rmiHost; - if (rmiHost != null) - connect(rmiHost); } public AdminUI() { + } + + /** + * Builds and displays the UI. Invoke this once, after construction, from a + * thread other than the AWT event-dispatch thread: it launches the + * frame-building helper thread and waits for it to finish. The thread starts + * are kept out of the constructor so that {@code this} does not escape to the + * helper threads before construction has completed (CodeQL + * java/thread-start-in-constructor). + */ + public void launch() { // // This is a workaround for JVM bug 4030718 in JDK1.3. // (See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4030718). @@ -855,7 +865,12 @@ public void run() { } public static void main(final String[] args) { - new AdminUI(args.length > 0 ? args[0] : null); + final String rmiHost = args.length > 0 ? args[0] : null; + final AdminUI adminUI = new AdminUI(rmiHost); + adminUI.launch(); + if (rmiHost != null) { + adminUI.connect(rmiHost); + } } /**