diff --git a/common/src/main/java/io/netty/util/HashedWheelTimer.java b/common/src/main/java/io/netty/util/HashedWheelTimer.java index 7bca40b9a7..20da06b592 100644 --- a/common/src/main/java/io/netty/util/HashedWheelTimer.java +++ b/common/src/main/java/io/netty/util/HashedWheelTimer.java @@ -76,9 +76,8 @@ public class HashedWheelTimer implements Timer { static final InternalLogger logger = InternalLoggerFactory.getInstance(HashedWheelTimer.class); - private static final ResourceLeakDetector leakDetector = - new ResourceLeakDetector( - HashedWheelTimer.class, 1, Runtime.getRuntime().availableProcessors() * 4); + private static final ResourceLeakDetector leakDetector = ResourceLeakDetectorFactory.instance() + .newResourceLeakDetector(HashedWheelTimer.class, 1, Runtime.getRuntime().availableProcessors() * 4L); private static final AtomicIntegerFieldUpdater WORKER_STATE_UPDATER; static { diff --git a/common/src/main/java/io/netty/util/ResourceLeakDetector.java b/common/src/main/java/io/netty/util/ResourceLeakDetector.java index 2a4b1c633e..a6e126d79d 100644 --- a/common/src/main/java/io/netty/util/ResourceLeakDetector.java +++ b/common/src/main/java/io/netty/util/ResourceLeakDetector.java @@ -109,7 +109,7 @@ public class ResourceLeakDetector { } // Should be power of two. - private static final int DEFAULT_SAMPLING_INTERVAL = 128; + static final int DEFAULT_SAMPLING_INTERVAL = 128; /** * @deprecated Use {@link #setLevel(Level)} instead. @@ -159,18 +159,36 @@ public class ResourceLeakDetector { private long leakCheckCnt; + /** + * @deprecated use {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class, int, long)}. + */ + @Deprecated public ResourceLeakDetector(Class resourceType) { this(simpleClassName(resourceType)); } + /** + * @deprecated use {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class, int, long)}. + */ + @Deprecated public ResourceLeakDetector(String resourceType) { this(resourceType, DEFAULT_SAMPLING_INTERVAL, Long.MAX_VALUE); } + /** + * This should not be used directly by users of {@link ResourceLeakDetector}. + * Please use {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class)} + * or {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class, int, long)} + */ + @SuppressWarnings("deprecation") public ResourceLeakDetector(Class resourceType, int samplingInterval, long maxActive) { this(simpleClassName(resourceType), samplingInterval, maxActive); } + /** + * @deprecated use {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class, int, long)}. + */ + @Deprecated public ResourceLeakDetector(String resourceType, int samplingInterval, long maxActive) { if (resourceType == null) { throw new NullPointerException("resourceType"); @@ -199,7 +217,7 @@ public class ResourceLeakDetector { * * @return the {@link ResourceLeak} or {@code null} */ - public ResourceLeak open(T obj) { + public final ResourceLeak open(T obj) { Level level = ResourceLeakDetector.level; if (level == Level.DISABLED) { return null; diff --git a/common/src/main/java/io/netty/util/ResourceLeakDetectorFactory.java b/common/src/main/java/io/netty/util/ResourceLeakDetectorFactory.java index c2fb71653a..d842c90c2a 100644 --- a/common/src/main/java/io/netty/util/ResourceLeakDetectorFactory.java +++ b/common/src/main/java/io/netty/util/ResourceLeakDetectorFactory.java @@ -61,60 +61,82 @@ public abstract class ResourceLeakDetectorFactory { * @param - the type of the resource class * @return - a new instance of {@link ResourceLeakDetector} */ - public abstract ResourceLeakDetector newResourceLeakDetector(final Class resource); + public final ResourceLeakDetector newResourceLeakDetector(Class resource) { + return newResourceLeakDetector(resource, ResourceLeakDetector.DEFAULT_SAMPLING_INTERVAL, Long.MAX_VALUE); + } + + /** + * Returns a new instance of a {@link ResourceLeakDetector} with the given resource class. + * + * @param resource - the resource class used to initialize the {@link ResourceLeakDetector} + * @param samplingInterval - the interval on which sampling takes place + * @param maxActive - the maximum active instances + * @param - the type of the resource class + * @return - a new instance of {@link ResourceLeakDetector} + */ + public abstract ResourceLeakDetector newResourceLeakDetector( + Class resource, int samplingInterval, long maxActive); /** * Default implementation that loads custom leak detector via system property */ private static final class DefaultResourceLeakDetectorFactory extends ResourceLeakDetectorFactory { + private final Constructor customClassConstructor; - private final String customLeakDetector; - private final Constructor customClassConstructor; - - public DefaultResourceLeakDetectorFactory() { - this.customLeakDetector = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public String run() { - return SystemPropertyUtil.get("io.netty.customResourceLeakDetector"); - } - }); - - this.customClassConstructor = customClassConstructor(); + DefaultResourceLeakDetectorFactory() { + String customLeakDetector; + try { + customLeakDetector = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public String run() { + return SystemPropertyUtil.get("io.netty.customResourceLeakDetector"); + } + }); + } catch (Throwable cause) { + logger.error("Could not access System property: io.netty.customResourceLeakDetector", cause); + customLeakDetector = null; + } + customClassConstructor = customLeakDetector == null ? null : customClassConstructor(customLeakDetector); } - private Constructor customClassConstructor() { + private static Constructor customClassConstructor(String customLeakDetector) { try { - if (customLeakDetector != null) { - final Class detectorClass = Class.forName(customLeakDetector, true, - PlatformDependent.getSystemClassLoader()); + final Class detectorClass = Class.forName(customLeakDetector, true, + PlatformDependent.getSystemClassLoader()); - if (ResourceLeakDetector.class.isAssignableFrom(detectorClass)) { - return detectorClass.getConstructor(Class.class); - } else { - logger.error("Class {} does not inherit from ResourceLeakDetector.", customLeakDetector); - } + if (ResourceLeakDetector.class.isAssignableFrom(detectorClass)) { + return detectorClass.getConstructor(Class.class, int.class, long.class); + } else { + logger.error("Class {} does not inherit from ResourceLeakDetector.", customLeakDetector); } } catch (Throwable t) { - logger.error("Could not load custom resource leak detector class provided: " + customLeakDetector, t); + logger.error("Could not load custom resource leak detector class provided: {}", + customLeakDetector, t); } return null; } @Override - public ResourceLeakDetector newResourceLeakDetector(final Class resource) { - try { - if (customClassConstructor != null) { + public ResourceLeakDetector newResourceLeakDetector( + Class resource, int samplingInterval, long maxActive) { + if (customClassConstructor != null) { + try { + @SuppressWarnings("unchecked") ResourceLeakDetector leakDetector = - (ResourceLeakDetector) customClassConstructor.newInstance(resource); - logger.debug("Loaded custom ResourceLeakDetector: {}", customLeakDetector); + (ResourceLeakDetector) customClassConstructor.newInstance( + resource, samplingInterval, maxActive); + logger.debug("Loaded custom ResourceLeakDetector: {}", + customClassConstructor.getDeclaringClass().getName()); return leakDetector; + } catch (Throwable t) { + logger.error( + "Could not load custom resource leak detector provided: {} with the given resource: {}", + customClassConstructor.getDeclaringClass().getName(), resource, t); } - } catch (Throwable t) { - logger.error("Could not load custom resource leak detector provided: {} with the given resource: {}", - customLeakDetector, resource, t); } - ResourceLeakDetector resourceLeakDetector = new ResourceLeakDetector(resource); + ResourceLeakDetector resourceLeakDetector = new ResourceLeakDetector( + resource, samplingInterval, maxActive); logger.debug("Loaded default ResourceLeakDetector: {}", resourceLeakDetector); return resourceLeakDetector; }