{"record":{"id":"8f137e67d438eaad","repo":"java-native-access/jna","slug":"comthread-executor-has-a-problem","errorCode":null,"errorMessage":"ComThread executor has a problem.","messagePattern":"ComThread executor has a problem\\.","errorType":"exception","errorClass":"java.lang.RuntimeException","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComThread.java","lineNumber":79,"sourceCode":"                    // a message loop see -\n                    // [http://www.codeguru.com/cpp/com-tech/activex/apts/article.php/c5529/Understanding-COM-Apartments-Part-I.htm]\n                    // [http://www.codeguru.com/cpp/com-tech/activex/apts/article.php/c5533/Understanding-COM-Apartments-Part-II.htm]\n                    WinNT.HRESULT hr = Ole32.INSTANCE.CoInitializeEx(null, coinitialiseExFlag);\n                    isCOMThread.set(true);\n                    COMUtils.checkRC(hr);\n                    ComThread.this.requiresInitialisation = false;\n                } catch (Throwable t) {\n                    ComThread.this.uncaughtExceptionHandler.uncaughtException(Thread.currentThread(), t);\n                }\n            }\n        };\n        executor = Executors.newSingleThreadExecutor(new ThreadFactory() {\n\n            @Override\n            public Thread newThread(Runnable r) {\n                if (!ComThread.this.requiresInitialisation) {\n                    // something has gone wrong!\n                    throw new RuntimeException(\"ComThread executor has a problem.\");\n                }\n                Thread thread = new Thread(r, threadName);\n                //make sure this is a daemon thread, or it will stop JVM existing\n                // if program does not call terminate();\n                thread.setDaemon(true);\n\n                thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {\n                    @Override\n                    public void uncaughtException(Thread t, Throwable e) {\n                        ComThread.this.requiresInitialisation = true;\n                        ComThread.this.uncaughtExceptionHandler.uncaughtException(t, e);\n                    }\n                });\n\n                return thread;\n            }\n        });\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComThread.java#L61-L97","documentation":"ComThread wraps a single dedicated COM-initialized thread in an ExecutorService. When the thread factory's newThread is invoked while requiresInitialisation is false, it concludes the executor is being re-created in a broken state and throws this RuntimeException. It signals an internal lifecycle invariant violation of the ComThread object, typically after terminate() or a failed initialisation.","triggerScenarios":"Reusing a ComThread instance after terminate() was called (executor shutdown triggers factory re-entry with stale state); constructing the executor twice on the same ComThread instance; concurrent use of ComThread from multiple threads racing on the requiresInitialisation flag.","commonSituations":"Calling terminate() then attempting to run another task on the same ComThread instead of creating a new one; application shutdown hooks racing with remaining submitted tasks; framework code (e.g. Spring bean destruction) closing ComThread while work is still queued.","solutions":["Never reuse a ComThread after terminate(); create a fresh ComThread for a new COM apartment","Ensure all tasks complete before calling terminate() and no tasks are submitted afterwards","Synchronize access so run() is not invoked concurrently with or after terminate()","If this appears without reuse, report it as a JNA bug with a reproducer"],"exampleFix":"// before\ncomThread.terminate();\ncomThread.run(task); // boom: executor has a problem\n// after\ncomThread.terminate();\nComThread newThread = new ComThread();\nnewThread.run(task);","handlingStrategy":"try-catch","validationCode":"if (comThread == null || terminated) throw new IllegalStateException(\"ComThread no longer usable; create a new one\");","typeGuard":null,"tryCatchPattern":"try { comThread.run(task); } catch (RuntimeException e) { if (e.getMessage().contains(\"executor has a problem\")) { comThread = new ComThread(); comThread.run(task); } }","preventionTips":["Create a new ComThread after terminate(); never reuse","Ensure all tasks finish before terminate()","Single-thread ownership of ComThread lifecycle"],"tags":["java","com","threading","executor","lifecycle"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}