ScanResult leaks shutdown hooks
See original GitHub issueThis code shows that a shutdown hook (ie unstarted thread) is created but not destroyed for each scan, even when using try-with-resources for ScanResult.
Seems like Runtime.getRuntime().removeShutdownHook()
might be needed. [EDIT: was addShutdownHook, nonsensically.]
import java.lang.reflect.Field;
import java.util.Map;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;
public class ClassGraphShutdownHooks {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 100_000; i++) {
try (ScanResult scan = new ClassGraph().scan()) {
}
System.out.printf("Number of shutdown hooks: %d%n", countShutdownHooks());
}
}
// thanks to https://stackoverflow.com/a/6865509/14379
// works on Java 8
private static int countShutdownHooks() throws ReflectiveOperationException {
Class clazz = Class.forName("java.lang.ApplicationShutdownHooks");
Field field = clazz.getDeclaredField("hooks");
field.setAccessible(true);
Map<?, ?> hooks = (Map<?, ?>) field.get(null);
return hooks.size();
}
}
Output:
Number of shutdown hooks: 1
Number of shutdown hooks: 2
Number of shutdown hooks: 3
Number of shutdown hooks: 4
Number of shutdown hooks: 5
Number of shutdown hooks: 6
Number of shutdown hooks: 7
Number of shutdown hooks: 8
Number of shutdown hooks: 9
Number of shutdown hooks: 10
...
(Related to https://github.com/classgraph/classgraph/issues/233)
Issue Analytics
- State:
- Created 5 years ago
- Comments:6 (6 by maintainers)
Top Results From Across the Web
shutdown hook causes classloader leak when library is used ...
Scanresult class adds a shutdown hook. This causes a classloader leak when tomcat unloads a webapplication that uses classgraph library.
Read more >ClassGraph library causes large memory leak in Geode after ...
ScanResult must be closed to avoid memory and file leaks. ... shutdown hook causes classloader leak when library is used inside a servlet ......
Read more >ClassLoader & memory leaks: a Java love story - Aloïs Micard
ApplicationShutdownHooks is used to register special code to be executed upon JVM shutdown, and since our JVM is not restarting in our case...
Read more >classgraph/classgraph classgraph-4.2.10 on GitHub - NewReleases.io
This means you have to close ScanResult instances yourself in a try-with-resources block (or rely on the shutdown hook to close the ScanResult...
Read more >Queries regarding Shutdown hook - Stack Overflow
1) You are correct. 2) The Java process' memory will be reclaimed, but you might want to do other cleanup, like delete some...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I don’t really trust WeakReferences either 😃, so I modified my code:
Now if I use try-with-resources as recommended, references don’t accumulate at all (nor hooks!):
On the other hand, if I fail to close the ScanResults, the finalizer keeps the weak-refs down:
Ah, I get it. Didn’t notice the bit in
close()
which was callingnonClosedWeakReferences.remove(weakReference)
.Excellent. Thanks @lukehutch!
Good to know. I have never needed them before, and there are tons of gotchas to using them right, so this has been a step learning curve. It was a good catch, thanks.