{"record":{"id":"4884d6375e325795","repo":"hs-web/hsweb-framework","slug":"object-is-recycled","errorCode":null,"errorMessage":"Object is recycled!","messagePattern":"Object is recycled!","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hsweb-core/src/main/java/org/hswebframework/web/recycler/RecyclerImpl.java","lineNumber":184,"sourceCode":"        while ((val = queue.poll()) != null) {\n            resetAndDestroy(val);\n        }\n    }\n\n    @AllArgsConstructor\n    static class OnceRecyclable<T> implements Recyclable<T> {\n        @SuppressWarnings(\"all\")\n        static final AtomicReferenceFieldUpdater<OnceRecyclable, Recyclable>\n            REF = AtomicReferenceFieldUpdater.newUpdater(OnceRecyclable.class, Recyclable.class, \"recyclable\");\n\n        private volatile Recyclable<T> recyclable;\n\n        @Override\n        public T get() {\n            @SuppressWarnings(\"unchecked\")\n            Recyclable<T> recyclable = REF.get(this);\n            if (recyclable == null) {\n                throw new IllegalStateException(\"Object is recycled!\");\n            }\n            return recyclable.get();\n        }\n\n        @Override\n        public void recycle() {\n            @SuppressWarnings(\"unchecked\")\n            Recyclable<T> recyclable = REF.getAndSet(this, null);\n            if (recyclable != null) {\n                recyclable.recycle();\n            }\n        }\n    }\n\n    @AllArgsConstructor\n    static class QueueRecyclable<T> implements Recyclable<T> {\n        @SuppressWarnings(\"all\")\n        static final AtomicReferenceFieldUpdater<QueueRecyclable, Object>","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/hs-web/hsweb-framework/blob/b2cfc85a57c70bf5b5cf6e7edae2d37102652ec8/hsweb-core/src/main/java/org/hswebframework/web/recycler/RecyclerImpl.java#L166-L202","documentation":"IllegalStateException raised from OnceRecyclable.get() when the internal recyclable reference has already been nulled out by recycle(). It fires on double-access after recycling: once a once-only Recyclable has been recycled, its object was reset and returned to the pool/destroyed, so any further get() would hand out a stale or repurposed object; the guard rejects that use with this error.","triggerScenarios":"Accessing ThreadLocalRecyclable.get() after recycle() was called on it (the REF handle was set to null). Called from the `ref` accessor path in doWith/take.","commonSituations":"Storing the recyclable wrapper and reusing it after returning the object to the pool; double-recycle then read; callbacks that run after the object was recycled.","solutions":["Do not call get() after recycle(); re-borrow via recycler.take()/doWith instead","Null out your local reference upon recycle so stale reads can't happen","Avoid keeping ThreadLocalRecyclable references beyond the scope of use","Check for double-recycle bugs in callback chains"],"exampleFix":"// before\nRecyclable<T> r = recycler.take(true);\nT v = r.get();\nr.recycle();\nT v2 = ((ThreadLocalRecyclable<T>) r).get();\n// after\nRecyclable<T> r = recycler.take(true);\nT v = r.get();\nr.recycle();\nr = recycler.take(true);\nT v2 = r.get();","handlingStrategy":"type-guard","validationCode":"T v = recyclable.get(); // capture before recycle","typeGuard":"static <T> T safeGet(ThreadLocalRecyclable<T> r) {\n    try { return r.get(); } catch (IllegalStateException e) { return null; }\n}","tryCatchPattern":"try {\n    return recyclable.get();\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"recycled\")) return null; // already returned to pool\n    throw e;\n}","preventionTips":["Extract values before calling recycle()","Never retain the wrapper past the use scope","Set local references to null after recycle","Avoid using recycled objects in callbacks"],"tags":["lifecycle","use-after-free","concurrency"],"backgroundTag":"use-after-recycle","analyzedSha":"b2cfc85a57c70bf5b5cf6e7edae2d37102652ec8","analyzedAt":"2026-09-13T09:05:02.172Z","contentChangedAt":"2026-09-13T09:05:02.172Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}