{"record":{"id":"880a417cca59cc7a","repo":"apache/flink","slug":"could-not-un-export-our-rmi-registry","errorCode":null,"errorMessage":"Could not un-export our RMI registry","messagePattern":"Could not un-export our RMI registry","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"flink-core/src/main/java/org/apache/flink/management/jmx/JMXServer.java","lineNumber":80,"sourceCode":"        }\n        internalStart(port);\n        this.port = port;\n    }\n\n    void stop() throws IOException {\n        rmiServerReference.set(null);\n        if (connector != null) {\n            try {\n                connector.stop();\n            } finally {\n                connector = null;\n            }\n        }\n        if (rmiRegistry != null) {\n            try {\n                UnicastRemoteObject.unexportObject(rmiRegistry, true);\n            } catch (NoSuchObjectException e) {\n                throw new IOException(\"Could not un-export our RMI registry\", e);\n            } finally {\n                rmiRegistry = null;\n            }\n        }\n    }\n\n    int getPort() {\n        return port;\n    }\n\n    private void internalStart(int port) throws IOException {\n        rmiServerReference.set(null);\n\n        // this allows clients to lookup the JMX service\n        rmiRegistry = new JmxRegistry(port, \"jmxrmi\", rmiServerReference);\n\n        String serviceUrl =\n                \"service:jmx:rmi://localhost:\" + port + \"/jndi/rmi://localhost:\" + port + \"/jmxrmi\";","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/management/jmx/JMXServer.java#L62-L98","documentation":"JMXServer.stop() shuts down the JMX connector server and then un-exports the RMI registry via UnicastRemoteObject.unexportObject. If that call throws NoSuchObjectException (the registry object is no longer exported — already unexported, garbage-collected, or shut down elsewhere), it is wrapped in IOException('Could not un-export our RMI registry'). It occurs during teardown, after the connector itself was stopped.","triggerScenarios":"Calling stop() twice on a JMXServer; a prior stop or an RMI-internal cleanup that already unexported the registry; JVM shutdown racing the explicit stop().","commonSituations":"Re-starting an embedded JMX server in tests (stop then start again) where the second stop finds the registry gone; shutdown hooks and explicit close both invoking stop(); RMI DGC collecting the registry between start and stop.","solutions":["Make stop() idempotent in calling code: null-check / set a stopped flag so it runs once.","Treat this IOException during shutdown as benign when the JVM/process is exiting anyway: catch and log at debug.","If you restart JMX servers repeatedly, create a fresh JMXServer instance per start rather than reusing one."],"exampleFix":"// before\njmxServer.stop(); // called from both shutdown hook and close()\n\n// after\nif (!stopped) {\n    stopped = true;\n    jmxServer.stop();\n}","handlingStrategy":"try-catch","validationCode":"if (!stopped) {\n    stopped = true;\n    jmxServer.stop();\n}","typeGuard":null,"tryCatchPattern":"try {\n    jmxServer.stop();\n} catch (IOException e) {\n    if (e.getCause() instanceof NoSuchObjectException) {\n        // registry already unexported; safe to ignore during shutdown\n        LOG.debug(\"JMX registry already unexported\", e);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Make stop() call sites idempotent with a flag or AtomicBoolean.","Guard shutdown hooks against racing explicit close()."],"tags":["jmx","rmi","shutdown","flink-core"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}