Use ResourceLeakDetectorFactory in HashedWheelTimer
Motivation: We recently added the ResourceLeakDetectorFactory but missed to updated HashedWheelTimer to use it. Modifications: - Add new abstract method to ResourceLeakDetectorFactory that allows to provide also samplingInterval and maxActive args. - Deprecate most constructors in ResourceLeakDetector and add doc explaining that people should use ResourceLeakDetectorFactory Result: Custom ResourceLeakDetectorFactory will also be used in HashedWheelTimer if configured.
This commit is contained in:
parent
bd0a74fca3
commit
57672d9854
@ -76,9 +76,8 @@ public class HashedWheelTimer implements Timer {
|
|||||||
static final InternalLogger logger =
|
static final InternalLogger logger =
|
||||||
InternalLoggerFactory.getInstance(HashedWheelTimer.class);
|
InternalLoggerFactory.getInstance(HashedWheelTimer.class);
|
||||||
|
|
||||||
private static final ResourceLeakDetector<HashedWheelTimer> leakDetector =
|
private static final ResourceLeakDetector<HashedWheelTimer> leakDetector = ResourceLeakDetectorFactory.instance()
|
||||||
new ResourceLeakDetector<HashedWheelTimer>(
|
.newResourceLeakDetector(HashedWheelTimer.class, 1, Runtime.getRuntime().availableProcessors() * 4L);
|
||||||
HashedWheelTimer.class, 1, Runtime.getRuntime().availableProcessors() * 4);
|
|
||||||
|
|
||||||
private static final AtomicIntegerFieldUpdater<HashedWheelTimer> WORKER_STATE_UPDATER;
|
private static final AtomicIntegerFieldUpdater<HashedWheelTimer> WORKER_STATE_UPDATER;
|
||||||
static {
|
static {
|
||||||
|
@ -109,7 +109,7 @@ public class ResourceLeakDetector<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Should be power of two.
|
// 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.
|
* @deprecated Use {@link #setLevel(Level)} instead.
|
||||||
@ -159,18 +159,36 @@ public class ResourceLeakDetector<T> {
|
|||||||
|
|
||||||
private long leakCheckCnt;
|
private long leakCheckCnt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class, int, long)}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public ResourceLeakDetector(Class<?> resourceType) {
|
public ResourceLeakDetector(Class<?> resourceType) {
|
||||||
this(simpleClassName(resourceType));
|
this(simpleClassName(resourceType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class, int, long)}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public ResourceLeakDetector(String resourceType) {
|
public ResourceLeakDetector(String resourceType) {
|
||||||
this(resourceType, DEFAULT_SAMPLING_INTERVAL, Long.MAX_VALUE);
|
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) {
|
public ResourceLeakDetector(Class<?> resourceType, int samplingInterval, long maxActive) {
|
||||||
this(simpleClassName(resourceType), samplingInterval, maxActive);
|
this(simpleClassName(resourceType), samplingInterval, maxActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class, int, long)}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public ResourceLeakDetector(String resourceType, int samplingInterval, long maxActive) {
|
public ResourceLeakDetector(String resourceType, int samplingInterval, long maxActive) {
|
||||||
if (resourceType == null) {
|
if (resourceType == null) {
|
||||||
throw new NullPointerException("resourceType");
|
throw new NullPointerException("resourceType");
|
||||||
@ -199,7 +217,7 @@ public class ResourceLeakDetector<T> {
|
|||||||
*
|
*
|
||||||
* @return the {@link ResourceLeak} or {@code null}
|
* @return the {@link ResourceLeak} or {@code null}
|
||||||
*/
|
*/
|
||||||
public ResourceLeak open(T obj) {
|
public final ResourceLeak open(T obj) {
|
||||||
Level level = ResourceLeakDetector.level;
|
Level level = ResourceLeakDetector.level;
|
||||||
if (level == Level.DISABLED) {
|
if (level == Level.DISABLED) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -61,60 +61,82 @@ public abstract class ResourceLeakDetectorFactory {
|
|||||||
* @param <T> - the type of the resource class
|
* @param <T> - the type of the resource class
|
||||||
* @return - a new instance of {@link ResourceLeakDetector}
|
* @return - a new instance of {@link ResourceLeakDetector}
|
||||||
*/
|
*/
|
||||||
public abstract <T> ResourceLeakDetector<T> newResourceLeakDetector(final Class<T> resource);
|
public final <T> ResourceLeakDetector<T> newResourceLeakDetector(Class<T> 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 <T> - the type of the resource class
|
||||||
|
* @return - a new instance of {@link ResourceLeakDetector}
|
||||||
|
*/
|
||||||
|
public abstract <T> ResourceLeakDetector<T> newResourceLeakDetector(
|
||||||
|
Class<T> resource, int samplingInterval, long maxActive);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementation that loads custom leak detector via system property
|
* Default implementation that loads custom leak detector via system property
|
||||||
*/
|
*/
|
||||||
private static final class DefaultResourceLeakDetectorFactory extends ResourceLeakDetectorFactory {
|
private static final class DefaultResourceLeakDetectorFactory extends ResourceLeakDetectorFactory {
|
||||||
|
private final Constructor<?> customClassConstructor;
|
||||||
|
|
||||||
private final String customLeakDetector;
|
DefaultResourceLeakDetectorFactory() {
|
||||||
private final Constructor customClassConstructor;
|
String customLeakDetector;
|
||||||
|
try {
|
||||||
public DefaultResourceLeakDetectorFactory() {
|
customLeakDetector = AccessController.doPrivileged(new PrivilegedAction<String>() {
|
||||||
this.customLeakDetector = AccessController.doPrivileged(new PrivilegedAction<String>() {
|
|
||||||
@Override
|
@Override
|
||||||
public String run() {
|
public String run() {
|
||||||
return SystemPropertyUtil.get("io.netty.customResourceLeakDetector");
|
return SystemPropertyUtil.get("io.netty.customResourceLeakDetector");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} catch (Throwable cause) {
|
||||||
this.customClassConstructor = customClassConstructor();
|
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 {
|
try {
|
||||||
if (customLeakDetector != null) {
|
|
||||||
final Class<?> detectorClass = Class.forName(customLeakDetector, true,
|
final Class<?> detectorClass = Class.forName(customLeakDetector, true,
|
||||||
PlatformDependent.getSystemClassLoader());
|
PlatformDependent.getSystemClassLoader());
|
||||||
|
|
||||||
if (ResourceLeakDetector.class.isAssignableFrom(detectorClass)) {
|
if (ResourceLeakDetector.class.isAssignableFrom(detectorClass)) {
|
||||||
return detectorClass.getConstructor(Class.class);
|
return detectorClass.getConstructor(Class.class, int.class, long.class);
|
||||||
} else {
|
} else {
|
||||||
logger.error("Class {} does not inherit from ResourceLeakDetector.", customLeakDetector);
|
logger.error("Class {} does not inherit from ResourceLeakDetector.", customLeakDetector);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
} 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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> ResourceLeakDetector<T> newResourceLeakDetector(final Class<T> resource) {
|
public <T> ResourceLeakDetector<T> newResourceLeakDetector(
|
||||||
try {
|
Class<T> resource, int samplingInterval, long maxActive) {
|
||||||
if (customClassConstructor != null) {
|
if (customClassConstructor != null) {
|
||||||
|
try {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
ResourceLeakDetector<T> leakDetector =
|
ResourceLeakDetector<T> leakDetector =
|
||||||
(ResourceLeakDetector<T>) customClassConstructor.newInstance(resource);
|
(ResourceLeakDetector<T>) customClassConstructor.newInstance(
|
||||||
logger.debug("Loaded custom ResourceLeakDetector: {}", customLeakDetector);
|
resource, samplingInterval, maxActive);
|
||||||
|
logger.debug("Loaded custom ResourceLeakDetector: {}",
|
||||||
|
customClassConstructor.getDeclaringClass().getName());
|
||||||
return leakDetector;
|
return leakDetector;
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.error("Could not load custom resource leak detector provided: {} with the given resource: {}",
|
logger.error(
|
||||||
customLeakDetector, resource, t);
|
"Could not load custom resource leak detector provided: {} with the given resource: {}",
|
||||||
|
customClassConstructor.getDeclaringClass().getName(), resource, t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceLeakDetector<T> resourceLeakDetector = new ResourceLeakDetector<T>(resource);
|
ResourceLeakDetector<T> resourceLeakDetector = new ResourceLeakDetector<T>(
|
||||||
|
resource, samplingInterval, maxActive);
|
||||||
logger.debug("Loaded default ResourceLeakDetector: {}", resourceLeakDetector);
|
logger.debug("Loaded default ResourceLeakDetector: {}", resourceLeakDetector);
|
||||||
return resourceLeakDetector;
|
return resourceLeakDetector;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user