hs-web/hsweb-framework · error · IllegalStateException
Object is recycled!
Error message
Object is recycled!
What it means
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.
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
Example fix
// before Recyclable<T> r = recycler.take(true); T v = r.get(); r.recycle(); T v2 = ((ThreadLocalRecyclable<T>) r).get(); // after Recyclable<T> r = recycler.take(true); T v = r.get(); r.recycle(); r = recycler.take(true); T v2 = r.get();
Defensive patterns
Strategy: type-guard
Validate before calling
T v = recyclable.get(); // capture before recycle
Type guard
static <T> T safeGet(ThreadLocalRecyclable<T> r) {
try { return r.get(); } catch (IllegalStateException e) { return null; }
} Try / catch
try {
return recyclable.get();
} catch (IllegalStateException e) {
if (e.getMessage().contains("recycled")) return null; // already returned to pool
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of hs-web/hsweb-framework@b2cfc85a57 (2026-09-13).
Data as JSON: /api/errors/4884d6375e325795.
Report an issue: GitHub.
Appendix: source
Thrown at hsweb-core/src/main/java/org/hswebframework/web/recycler/RecyclerImpl.java:184
while ((val = queue.poll()) != null) {
resetAndDestroy(val);
}
}
@AllArgsConstructor
static class OnceRecyclable<T> implements Recyclable<T> {
@SuppressWarnings("all")
static final AtomicReferenceFieldUpdater<OnceRecyclable, Recyclable>
REF = AtomicReferenceFieldUpdater.newUpdater(OnceRecyclable.class, Recyclable.class, "recyclable");
private volatile Recyclable<T> recyclable;
@Override
public T get() {
@SuppressWarnings("unchecked")
Recyclable<T> recyclable = REF.get(this);
if (recyclable == null) {
throw new IllegalStateException("Object is recycled!");
}
return recyclable.get();
}
@Override
public void recycle() {
@SuppressWarnings("unchecked")
Recyclable<T> recyclable = REF.getAndSet(this, null);
if (recyclable != null) {
recyclable.recycle();
}
}
}
@AllArgsConstructor
static class QueueRecyclable<T> implements Recyclable<T> {
@SuppressWarnings("all")
static final AtomicReferenceFieldUpdater<QueueRecyclable, Object>View on GitHub (pinned to b2cfc85a57)