{"record":{"id":"ae4c7e910f9995ba","repo":"apache/cassandra","slug":"cannot-create-a-sharedcopy-of-a-safememory-object","errorCode":null,"errorMessage":"Cannot create a sharedCopy of a SafeMemory object that has already been closed","messagePattern":"Cannot create a sharedCopy of a SafeMemory object that has already been closed","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/io/util/SafeMemory.java","lineNumber":45,"sourceCode":"\npublic class SafeMemory extends Memory implements SharedCloseable\n{\n    private final Ref<?> ref;\n    public SafeMemory(long size)\n    {\n        super(size);\n        ref = new Ref<>(null, new MemoryTidy(peer, size));\n    }\n\n    private SafeMemory(SafeMemory copyOf)\n    {\n        super(copyOf);\n        ref = copyOf.ref.ref();\n        /** see {@link Memory#Memory(long)} re: null pointers*/\n        if (peer == 0 && size != 0)\n        {\n            ref.ensureReleased();\n            throw new IllegalStateException(\"Cannot create a sharedCopy of a SafeMemory object that has already been closed\");\n        }\n    }\n\n    public SafeMemory sharedCopy()\n    {\n        return new SafeMemory(this);\n    }\n\n    public void free()\n    {\n        ref.release();\n        peer = 0;\n    }\n\n    public void close()\n    {\n        ref.ensureReleased();\n        peer = 0;","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/util/SafeMemory.java#L27-L63","documentation":"SafeMemory's copy constructor calls ref.ensureReleased() when the copy's peer pointer is null but the size is non-zero, meaning the source SafeMemory was already closed (its native memory freed). It throws IllegalStateException to prevent handing out a shared copy of freed off-heap memory. Accessing such memory would otherwise crash the JVM.","triggerScenarios":"Calling new SafeMemory(existing) or existing.sharedCopy() after the source SafeMemory has been closed via close() (or try-with-resources exiting its scope).","commonSituations":"Sharing a SafeMemory across threads where one thread closes it while another still holds a reference; use-after-close in try-with-resources; keeping a copy of a Rebuffer/Memory-managed buffer beyond its owner's lifetime.","solutions":["Ensure the source SafeMemory is still open before calling sharedCopy(); restructure ownership so closer is the last user","Call sharedCopy() before the source is closed and manage the copy's lifecycle independently","Wrap shared copies in try-with-resources and avoid closing shared copies while other copies are live","Use ref-counted access (the ref() handle) to coordinate close across threads"],"exampleFix":"// before\ntry (SafeMemory mem = acquire()) { sharedHolder.set(mem); } // closed on exit\nSafeMemory copy = sharedHolder.get().sharedCopy(); // throws\n// after\ntry (SafeMemory mem = acquire()) { sharedHolder.set(mem.sharedCopy()); }\nSafeMemory copy = sharedHolder.get().sharedCopy(); // valid","handlingStrategy":"try-catch","validationCode":"if (source.isClosed()) throw new IllegalStateException(\"source already closed\"); // or track open state yourself","typeGuard":"boolean usable(SafeMemory m) { return m != null && !m.isClosed(); }","tryCatchPattern":"try { SafeMemory copy = mem.sharedCopy(); } catch (IllegalStateException e) { /* recreate source or skip */ }","preventionTips":["Use try-with-resources and never let closed sources escape their scope","Call sharedCopy() while the source is definitely open","Centralize SafeMemory ownership in one component that closes last","Prefer ref.count()/ensureReleased-aware handles for cross-thread sharing"],"tags":["off-heap-memory","use-after-close","illegal-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}