Remove deprecated stuff around ResourceLeakDetector (#11572)

Motivation:
A number of classes and APIs around the ResourceLeakDetector have been deprecated for removal in Netty 5.x, because better alternatives exist.

Modification:
Remove everything in and around ResourceLeakDetector that is deprecated, and fix the few usages that were found.

Result:
Less deprecated code.
This commit is contained in:
Chris Vest 2021-08-11 21:41:49 +02:00 committed by GitHub
parent 11fcfe1f73
commit a3d5617d45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 22 additions and 267 deletions

View File

@ -1,42 +0,0 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.util;
/**
* @deprecated please use {@link ResourceLeakTracker} as it may lead to false-positives.
*/
@Deprecated
public interface ResourceLeak {
/**
* Records the caller's current stack trace so that the {@link ResourceLeakDetector} can tell where the leaked
* resource was accessed lastly. This method is a shortcut to {@link #record(Object) record(null)}.
*/
void record();
/**
* Records the caller's current stack trace and the specified additional arbitrary information
* so that the {@link ResourceLeakDetector} can tell where the leaked resource was accessed lastly.
*/
void record(Object hint);
/**
* Close the leak so that {@link ResourceLeakDetector} does not warn about leaked resources.
*
* @return {@code true} if called first time, {@code false} if called already
*/
boolean close();
}

View File

@ -114,14 +114,6 @@ public class ResourceLeakDetector<T> {
}
}
/**
* @deprecated Use {@link #setLevel(Level)} instead.
*/
@Deprecated
public static void setEnabled(boolean enabled) {
setLevel(enabled? Level.SIMPLE : Level.DISABLED);
}
/**
* Returns {@code true} if resource leak detection is enabled.
*/
@ -154,70 +146,15 @@ public class ResourceLeakDetector<T> {
private final int samplingInterval;
/**
* @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);
}
/**
* @deprecated Use {@link ResourceLeakDetector#ResourceLeakDetector(Class, int)}.
* <p>
* This should not be used directly by users of {@link ResourceLeakDetector}.
* Please use {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class)}
* or {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class, int, long)}
*
* @param maxActive This is deprecated and will be ignored.
* or {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class, int)}
*/
@Deprecated
public ResourceLeakDetector(Class<?> resourceType, int samplingInterval, long maxActive) {
this(resourceType, samplingInterval);
}
/**
* 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) {
this(simpleClassName(resourceType), samplingInterval, Long.MAX_VALUE);
}
/**
* @deprecated use {@link ResourceLeakDetectorFactory#newResourceLeakDetector(Class, int, long)}.
* <p>
* @param maxActive This is deprecated and will be ignored.
*/
@Deprecated
public ResourceLeakDetector(String resourceType, int samplingInterval, long maxActive) {
requireNonNull(resourceType, "resourceType");
this.resourceType = resourceType;
this.resourceType = simpleClassName(resourceType);
this.samplingInterval = samplingInterval;
}
/**
* Creates a new {@link ResourceLeak} which is expected to be closed via {@link ResourceLeak#close()} when the
* related resource is deallocated.
*
* @return the {@link ResourceLeak} or {@code null}
* @deprecated use {@link #track(Object)}
*/
@Deprecated
public final ResourceLeak open(T obj) {
return track0(obj);
}
/**
* Creates a new {@link ResourceLeakTracker} which is expected to be closed via
* {@link ResourceLeakTracker#close(Object)} when the related resource is deallocated.
@ -326,9 +263,8 @@ public class ResourceLeakDetector<T> {
protected void reportInstancesLeak(String resourceType) {
}
@SuppressWarnings("deprecation")
private static final class DefaultResourceLeak<T>
extends WeakReference<Object> implements ResourceLeakTracker<T>, ResourceLeak {
extends WeakReference<Object> implements ResourceLeakTracker<T> {
@SuppressWarnings("unchecked") // generics and updaters do not mix.
private static final AtomicReferenceFieldUpdater<DefaultResourceLeak<?>, TraceRecord> headUpdater =
@ -438,7 +374,11 @@ public class ResourceLeakDetector<T> {
}
@Override
public boolean close() {
public boolean close(T trackedObject) {
// Ensure that the object that was tracked is the same as the one that was passed to close(...).
assert trackedHash == System.identityHashCode(trackedObject);
try {
if (allLeaks.remove(this)) {
// Call clear so the reference is not even enqueued.
clear();
@ -446,15 +386,6 @@ public class ResourceLeakDetector<T> {
return true;
}
return false;
}
@Override
public boolean close(T trackedObject) {
// Ensure that the object that was tracked is the same as the one that was passed to close(...).
assert trackedHash == System.identityHashCode(trackedObject);
try {
return close();
} finally {
// Ensure the tracked object remain live and strongly referenced, until close() has finished.
Reference.reachabilityFence(trackedObject);
@ -518,7 +449,7 @@ public class ResourceLeakDetector<T> {
private static final AtomicReference<String[]> excludedMethods =
new AtomicReference<>(EmptyArrays.EMPTY_STRINGS);
public static void addExclusions(Class clz, String ... methodNames) {
public static void addExclusions(Class<?> clz, String ... methodNames) {
Set<String> nameSet = new HashSet<>(Arrays.asList(methodNames));
// Use loop rather than lookup. This avoids knowing the parameters, and doesn't have to handle
// NoSuchMethodException.

View File

@ -66,39 +66,20 @@ public abstract class ResourceLeakDetectorFactory {
}
/**
* @deprecated Use {@link #newResourceLeakDetector(Class, int)} instead.
* <p>
* 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 This is deprecated and will be ignored.
* @param <T> the type of the resource class
* @return a new instance of {@link ResourceLeakDetector}
*/
@Deprecated
public abstract <T> ResourceLeakDetector<T> newResourceLeakDetector(
Class<T> resource, int samplingInterval, long maxActive);
/**
* 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 <T> the type of the resource class
* @return a new instance of {@link ResourceLeakDetector}
*/
@SuppressWarnings("deprecation")
public <T> ResourceLeakDetector<T> newResourceLeakDetector(Class<T> resource, int samplingInterval) {
ObjectUtil.checkPositive(samplingInterval, "samplingInterval");
return newResourceLeakDetector(resource, samplingInterval, Long.MAX_VALUE);
}
Class<T> resource, int samplingInterval);
/**
* Default implementation that loads custom leak detector via system property
*/
private static final class DefaultResourceLeakDetectorFactory extends ResourceLeakDetectorFactory {
private final Constructor<?> obsoleteCustomClassConstructor;
private final Constructor<?> customClassConstructor;
DefaultResourceLeakDetectorFactory() {
@ -110,30 +91,12 @@ public abstract class ResourceLeakDetectorFactory {
customLeakDetector = null;
}
if (customLeakDetector == null) {
obsoleteCustomClassConstructor = customClassConstructor = null;
customClassConstructor = null;
} else {
obsoleteCustomClassConstructor = obsoleteCustomClassConstructor(customLeakDetector);
customClassConstructor = customClassConstructor(customLeakDetector);
}
}
private static Constructor<?> obsoleteCustomClassConstructor(String customLeakDetector) {
try {
final Class<?> detectorClass = Class.forName(customLeakDetector, true,
PlatformDependent.getSystemClassLoader());
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);
}
return null;
}
private static Constructor<?> customClassConstructor(String customLeakDetector) {
try {
final Class<?> detectorClass = Class.forName(customLeakDetector, true,
@ -151,34 +114,9 @@ public abstract class ResourceLeakDetectorFactory {
return null;
}
@SuppressWarnings("deprecation")
@Override
public <T> ResourceLeakDetector<T> newResourceLeakDetector(Class<T> resource, int samplingInterval,
long maxActive) {
if (obsoleteCustomClassConstructor != null) {
try {
@SuppressWarnings("unchecked")
ResourceLeakDetector<T> leakDetector =
(ResourceLeakDetector<T>) obsoleteCustomClassConstructor.newInstance(
resource, samplingInterval, maxActive);
logger.debug("Loaded custom ResourceLeakDetector: {}",
obsoleteCustomClassConstructor.getDeclaringClass().getName());
return leakDetector;
} catch (Throwable t) {
logger.error(
"Could not load custom resource leak detector provided: {} with the given resource: {}",
obsoleteCustomClassConstructor.getDeclaringClass().getName(), resource, t);
}
}
ResourceLeakDetector<T> resourceLeakDetector = new ResourceLeakDetector<>(resource, samplingInterval,
maxActive);
logger.debug("Loaded default ResourceLeakDetector: {}", resourceLeakDetector);
return resourceLeakDetector;
}
@Override
public <T> ResourceLeakDetector<T> newResourceLeakDetector(Class<T> resource, int samplingInterval) {
ObjectUtil.checkPositive(samplingInterval, "samplingInterval");
if (customClassConstructor != null) {
try {
@SuppressWarnings("unchecked")

View File

@ -1,70 +0,0 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.util;
import java.util.Arrays;
/**
* @deprecated This class will be removed in the future version.
*/
@Deprecated
public class ResourceLeakException extends RuntimeException {
private static final long serialVersionUID = 7186453858343358280L;
private final StackTraceElement[] cachedStackTrace;
public ResourceLeakException() {
cachedStackTrace = getStackTrace();
}
public ResourceLeakException(String message) {
super(message);
cachedStackTrace = getStackTrace();
}
public ResourceLeakException(String message, Throwable cause) {
super(message, cause);
cachedStackTrace = getStackTrace();
}
public ResourceLeakException(Throwable cause) {
super(cause);
cachedStackTrace = getStackTrace();
}
@Override
public int hashCode() {
int hashCode = 0;
for (StackTraceElement e: cachedStackTrace) {
hashCode = hashCode * 31 + e.hashCode();
}
return hashCode;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ResourceLeakException)) {
return false;
}
if (o == this) {
return true;
}
return Arrays.equals(cachedStackTrace, ((ResourceLeakException) o).cachedStackTrace);
}
}

View File

@ -76,8 +76,8 @@ public class ResourceLeakDetectorTest {
}
boolean closed = r.close();
if (checkClosed && !closed) {
error.compareAndSet(null,
new AssertionError("ResourceLeak.close() returned 'false' but expected 'true'"));
error.compareAndSet(null, new AssertionError(
"ResourceLeakTracker.close() returned 'false' but expected 'true'"));
return true;
}
}
@ -121,8 +121,7 @@ public class ResourceLeakDetectorTest {
private static final class DefaultResource implements Resource {
// Sample every allocation
static final TestResourceLeakDetector<Resource> detector = new TestResourceLeakDetector<>(
Resource.class, 1, Integer.MAX_VALUE);
static final TestResourceLeakDetector<Resource> detector = new TestResourceLeakDetector<>(Resource.class, 1);
@Override
public boolean close() {
@ -145,8 +144,8 @@ public class ResourceLeakDetectorTest {
private final AtomicReference<Throwable> error = new AtomicReference<>();
TestResourceLeakDetector(Class<?> resourceType, int samplingInterval, long maxActive) {
super(resourceType, samplingInterval, maxActive);
TestResourceLeakDetector(Class<?> resourceType, int samplingInterval) {
super(resourceType, samplingInterval);
}
@Override

View File

@ -26,11 +26,11 @@ public class ResourceLeakDetectorBenchmark extends AbstractMicrobenchmark {
@Setup
public void setup() {
detector = new ResourceLeakDetector<>(getClass(), 128, Long.MAX_VALUE);
detector = new ResourceLeakDetector<>(getClass(), 128);
}
@Benchmark
public Object open() {
return detector.open(DUMMY);
return detector.track(DUMMY);
}
}

View File

@ -32,8 +32,7 @@ public class ResourceLeakDetectorRecordBenchmark extends AbstractMicrobenchmark
private int recordTimes;
private ResourceLeakDetector.Level level;
ResourceLeakDetector<Object> detector = new ResourceLeakDetector<Object>(
Object.class, 1, Integer.MAX_VALUE) {
ResourceLeakDetector<Object> detector = new ResourceLeakDetector<Object>(Object.class, 1) {
@Override
protected void reportTracedLeak(String resourceType, String records) {
// noop