Merge pull request #619 from DataDog/mar-kolya/fix-memory-leak-in-weak-map
Mar kolya/fix memory leak in weak map
This commit is contained in:
commit
44aadf36ce
|
@ -54,7 +54,7 @@ class WeakMapSuppliers {
|
||||||
};
|
};
|
||||||
|
|
||||||
private final ScheduledExecutorService cleanerExecutorService;
|
private final ScheduledExecutorService cleanerExecutorService;
|
||||||
|
private final Thread shutdownCallback;
|
||||||
private final Queue<WeakReference<WeakConcurrentMap>> suppliedMaps =
|
private final Queue<WeakReference<WeakConcurrentMap>> suppliedMaps =
|
||||||
new ConcurrentLinkedQueue<>();
|
new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
|
@ -62,14 +62,16 @@ class WeakMapSuppliers {
|
||||||
|
|
||||||
WeakConcurrent() {
|
WeakConcurrent() {
|
||||||
cleanerExecutorService = Executors.newScheduledThreadPool(1, THREAD_FACTORY);
|
cleanerExecutorService = Executors.newScheduledThreadPool(1, THREAD_FACTORY);
|
||||||
|
shutdownCallback = new ShutdownCallback(cleanerExecutorService);
|
||||||
|
|
||||||
cleanerExecutorService.scheduleAtFixedRate(
|
cleanerExecutorService.scheduleAtFixedRate(
|
||||||
new CleanupRunnable(cleanerExecutorService, suppliedMaps, finalized),
|
new CleanupRunnable(cleanerExecutorService, shutdownCallback, suppliedMaps, finalized),
|
||||||
CLEAN_FREQUENCY_SECONDS,
|
CLEAN_FREQUENCY_SECONDS,
|
||||||
CLEAN_FREQUENCY_SECONDS,
|
CLEAN_FREQUENCY_SECONDS,
|
||||||
TimeUnit.SECONDS);
|
TimeUnit.SECONDS);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Runtime.getRuntime().addShutdownHook(new ShutdownCallback(cleanerExecutorService));
|
Runtime.getRuntime().addShutdownHook(shutdownCallback);
|
||||||
} catch (final IllegalStateException ex) {
|
} catch (final IllegalStateException ex) {
|
||||||
// The JVM is already shutting down.
|
// The JVM is already shutting down.
|
||||||
}
|
}
|
||||||
|
@ -90,14 +92,17 @@ class WeakMapSuppliers {
|
||||||
private static class CleanupRunnable implements Runnable {
|
private static class CleanupRunnable implements Runnable {
|
||||||
|
|
||||||
private final ScheduledExecutorService executorService;
|
private final ScheduledExecutorService executorService;
|
||||||
|
private final Thread shutdownCallback;
|
||||||
private final Queue<WeakReference<WeakConcurrentMap>> suppliedMaps;
|
private final Queue<WeakReference<WeakConcurrentMap>> suppliedMaps;
|
||||||
private final AtomicBoolean finalized;
|
private final AtomicBoolean finalized;
|
||||||
|
|
||||||
public CleanupRunnable(
|
public CleanupRunnable(
|
||||||
final ScheduledExecutorService executorService,
|
final ScheduledExecutorService executorService,
|
||||||
|
final Thread shutdownCallback,
|
||||||
final Queue<WeakReference<WeakConcurrentMap>> suppliedMaps,
|
final Queue<WeakReference<WeakConcurrentMap>> suppliedMaps,
|
||||||
final AtomicBoolean finalized) {
|
final AtomicBoolean finalized) {
|
||||||
this.executorService = executorService;
|
this.executorService = executorService;
|
||||||
|
this.shutdownCallback = shutdownCallback;
|
||||||
this.suppliedMaps = suppliedMaps;
|
this.suppliedMaps = suppliedMaps;
|
||||||
this.finalized = finalized;
|
this.finalized = finalized;
|
||||||
}
|
}
|
||||||
|
@ -115,6 +120,7 @@ class WeakMapSuppliers {
|
||||||
}
|
}
|
||||||
if (finalized.get() && suppliedMaps.isEmpty()) {
|
if (finalized.get() && suppliedMaps.isEmpty()) {
|
||||||
executorService.shutdown();
|
executorService.shutdown();
|
||||||
|
Runtime.getRuntime().removeShutdownHook(shutdownCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ class WeakConcurrentSupplierTest extends Specification {
|
||||||
|
|
||||||
// Hit map a few times to trigger unreferenced entries cleanup.
|
// Hit map a few times to trigger unreferenced entries cleanup.
|
||||||
// Exact number of times that we need to hit map is implementation dependent.
|
// Exact number of times that we need to hit map is implementation dependent.
|
||||||
// For Guava it i specified in
|
// For Guava it is specified in
|
||||||
// com.google.common.collect.MapMakerInternalMap.DRAIN_THRESHOLD = 0x3F
|
// com.google.common.collect.MapMakerInternalMap.DRAIN_THRESHOLD = 0x3F
|
||||||
if (name == "Guava" || name == "WeakInline") {
|
if (name == "Guava" || name == "WeakInline") {
|
||||||
for (int i = 0; i <= 0x3F; i++) {
|
for (int i = 0; i <= 0x3F; i++) {
|
||||||
|
|
|
@ -60,6 +60,11 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
private final Map<String, String> defaultSpanTags;
|
private final Map<String, String> defaultSpanTags;
|
||||||
/** A configured mapping of service names to update with new values */
|
/** A configured mapping of service names to update with new values */
|
||||||
private final Map<String, String> serviceNameMappings;
|
private final Map<String, String> serviceNameMappings;
|
||||||
|
/**
|
||||||
|
* JVM shutdown callback, keeping a reference to it to remove this if DDTracer gets destroyed
|
||||||
|
* earlier
|
||||||
|
*/
|
||||||
|
private final Thread shutdownCallback;
|
||||||
|
|
||||||
/** Span context decorators */
|
/** Span context decorators */
|
||||||
private final Map<String, List<AbstractDecorator>> spanContextDecorators =
|
private final Map<String, List<AbstractDecorator>> spanContextDecorators =
|
||||||
|
@ -163,15 +168,15 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
this.runtimeId = runtimeId;
|
this.runtimeId = runtimeId;
|
||||||
this.serviceNameMappings = serviceNameMappings;
|
this.serviceNameMappings = serviceNameMappings;
|
||||||
|
|
||||||
|
shutdownCallback =
|
||||||
|
new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
};
|
||||||
try {
|
try {
|
||||||
Runtime.getRuntime()
|
Runtime.getRuntime().addShutdownHook(shutdownCallback);
|
||||||
.addShutdownHook(
|
|
||||||
new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (final IllegalStateException ex) {
|
} catch (final IllegalStateException ex) {
|
||||||
// The JVM is already shutting down.
|
// The JVM is already shutting down.
|
||||||
}
|
}
|
||||||
|
@ -200,6 +205,12 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
log.info("New instance: {}", this);
|
log.info("New instance: {}", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finalize() {
|
||||||
|
Runtime.getRuntime().removeShutdownHook(shutdownCallback);
|
||||||
|
shutdownCallback.run();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of span context decorators
|
* Returns the list of span context decorators
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue