private void tryReturnToPool(T object, ObjectId objectId, Cleaner cleaner, ObjectLeakNotifier notifier) { long currentPoolSize; do { currentPoolSize = poolSize.get(); if (currentPoolSize >= objectsCacheMaxCount) { notifier.disable(); // Effectively does nothing, because notifier is disabled above. The purpose of this call is to deregister the // cleaner from the internal global linked list of all cleaners in the JVM, and let it be reclaimed itself. cleaner.clean(); // Important to use the objectId after notifier.disable() (in the logging statement below), otherwise VM may // already decide that the objectId is unreachable and run Cleaner before notifier.disable(), that would be // reported as a false-positive "leak". Ideally reachabilityFence(objectId) should be inserted here. log.debug("cache num entries is exceeding in [%s], objectId [%s]", this, objectId); return; } } while (!poolSize.compareAndSet(currentPoolSize, currentPoolSize + 1)); if (!objects.offer(new ObjectResourceHolder(object, objectId, cleaner, notifier))) { impossibleOffsetFailed(object, objectId, cleaner, notifier); } }
/** * This should be impossible, because {@link ConcurrentLinkedQueue#offer(Object)} event don't have `return false;` in * it's body in OpenJDK 8. */ private void impossibleOffsetFailed(T object, ObjectId objectId, Cleaner cleaner, ObjectLeakNotifier notifier) { poolSize.decrementAndGet(); notifier.disable(); // Effectively does nothing, because notifier is disabled above. The purpose of this call is to deregister the // cleaner from the internal global linked list of all cleaners in the JVM, and let it be reclaimed itself. cleaner.clean(); log.error( new ISE("Queue offer failed"), "Could not offer object [%s] back into the queue, objectId [%s]", object, objectId ); }
private void tryReturnToPool(T object, ObjectId objectId, Cleaner cleaner, ObjectLeakNotifier notifier) { long currentPoolSize; do { currentPoolSize = poolSize.get(); if (currentPoolSize >= objectsCacheMaxCount) { notifier.disable(); // Effectively does nothing, because notifier is disabled above. The purpose of this call is to deregister the // cleaner from the internal global linked list of all cleaners in the JVM, and let it be reclaimed itself. cleaner.clean(); // Important to use the objectId after notifier.disable() (in the logging statement below), otherwise VM may // already decide that the objectId is unreachable and run Cleaner before notifier.disable(), that would be // reported as a false-positive "leak". Ideally reachabilityFence(objectId) should be inserted here. log.debug("cache num entries is exceeding in [%s], objectId [%s]", this, objectId); return; } } while (!poolSize.compareAndSet(currentPoolSize, currentPoolSize + 1)); if (!objects.offer(new ObjectResourceHolder(object, objectId, cleaner, notifier))) { impossibleOffsetFailed(object, objectId, cleaner, notifier); } }
/** * This should be impossible, because {@link ConcurrentLinkedQueue#offer(Object)} event don't have `return false;` in * it's body in OpenJDK 8. */ private void impossibleOffsetFailed(T object, ObjectId objectId, Cleaner cleaner, ObjectLeakNotifier notifier) { poolSize.decrementAndGet(); notifier.disable(); // Effectively does nothing, because notifier is disabled above. The purpose of this call is to deregister the // cleaner from the internal global linked list of all cleaners in the JVM, and let it be reclaimed itself. cleaner.clean(); log.error( new ISE("Queue offer failed"), "Could not offer object [%s] back into the queue, objectId [%s]", object, objectId ); }