{"record":{"id":"199dd0f850a07a88","repo":"apache/flink","slug":"trying-to-access-closed-classloader-please-check","errorCode":null,"errorMessage":"Trying to access closed classloader. Please check if you store classloaders directly or indirectly in static fields. If the stacktrace suggests that the leak occurs in a third party library and cannot be fixed immediately, you can disable this check with the configuration '{CoreOptions.CHECK_LEAKED_CLASSLOADER.key()}'.","messagePattern":"Trying to access closed classloader\\. Please check if you store classloaders directly or indirectly in static fields\\. If the stacktrace suggests that the leak occurs in a third party library and cannot be fixed immediately, you can disable this check with the configuration '(.+?)'\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/util/FlinkUserCodeClassLoaders.java","lineNumber":184,"sourceCode":"            this.inner = inner;\n        }\n\n        @Override\n        public void close() {\n            final FlinkUserCodeClassLoader inner = this.inner;\n            if (inner != null) {\n                try {\n                    inner.close();\n                } catch (IOException e) {\n                    LOG.warn(\"Could not close user classloader\", e);\n                }\n            }\n            this.inner = null;\n        }\n\n        private FlinkUserCodeClassLoader ensureInner() {\n            if (inner == null) {\n                throw new IllegalStateException(\n                        \"Trying to access closed classloader. Please check if you store \"\n                                + \"classloaders directly or indirectly in static fields. If the stacktrace suggests that the leak \"\n                                + \"occurs in a third party library and cannot be fixed immediately, you can disable this check \"\n                                + \"with the configuration '\"\n                                + CoreOptions.CHECK_LEAKED_CLASSLOADER.key()\n                                + \"'.\");\n            }\n            return inner;\n        }\n\n        @Override\n        public Class<?> loadClass(String name) throws ClassNotFoundException {\n            return ensureInner().loadClass(name);\n        }\n\n        @Override\n        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {\n            // called for dynamic class loading","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/util/FlinkUserCodeClassLoaders.java#L166-L202","documentation":"SafetyNetWrapperClassLoader.ensureInner fires IllegalStateException when a user-code class loader is used after it was closed. Flink closes user classloaders when a job reaches a terminal state to detect classloader leaks; any later loadClass/resource call through the wrapper hits inner == null and this message tells you a static field, ThreadLocal, or cached object still references the loader. The message also names the escape hatch: the 'classloader.check-leaked-classloader' config key (CoreOptions.CHECK_LEAKED_CLASSLOADER).","triggerScenarios":"A job class or third-party library caches the context classloader, a class, or an object holding a class reference in a static/ThreadLocal field; after the job finishes/fails and Flink closes the loader, a lingering thread or shutdown hook triggers classloading through it.","commonSituations":"Libraries with static caches ( JDBC drivers, logging configs, caches like Guava/Caffeine with strong refs, Akka/Pekko, Jackson mappers capturing the loader), driver threads outliving the job, or reused executors inside user code on session clusters.","solutions":["Find the holder from the stack trace: clear the static field / ThreadLocal / cache when the job's close() or RichFunction.close() runs","As a temporary workaround set classloader.check-leaked-classloader: false — the leak remains but the check no longer throws (memory still grows on session clusters)","Move the offending library's initialization to the parent classloader (e.g. put the jar in Flink's lib/ instead of the user jar)","Ensure threads and executors created in user code are shut down in close() so nothing outlives the classloader"],"exampleFix":"// before\npublic class MyFunction extends RichMapFunction<..> {\n    private static final ObjectMapper MAPPER = new ObjectMapper(); // can pin loader\n}\n// after\npublic class MyFunction extends RichMapFunction<..> {\n    private ObjectMapper mapper; // instance field, created in open(), released with the loader\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    Class<?> c = userClassLoader.loadClass(name);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"closed classloader\")) { /* job already terminal: abandon cached loader */ }\n}","preventionTips":["Never store classes, classloaders, or instances of user classes in static/ThreadLocal fields from library code","Release caches and shut down threads/executors in close() lifecycle methods","Run shared heavy libraries from lib/ (parent loader) instead of the user jar","Use classloader.check-leaked-classloader: false only as a temporary measure — the leak remains"],"tags":["classloader","memory-leak","session-cluster","shutdown"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}