Open mhnot opened 4 years ago
Hi @mhnot,
The whole thing runs using one thread only so we optimize for CPU, the process can eat lot of memory. How much memory do you give it? My guess is that it's GC pauses, especially if it eats your whole CPU (compared to one thread).
I use spotbugs in a rather large eclipse workspace consisting of around 140 java projects with a few hundred jars. Eclipse is started with 4GB max heap.
My machine has 4 cores with 8 logical processors. All of them are busy after starting spotbugs within eclipse. I captured multiple thread dumps and every one contains 8 "RUNNABLE" findbugs threads. And multiple of these 8 threads are running findsecbugs while others are busy with stadard spotbugs analysis.
This is the progress view from eclipse showing also multiple parallel operations:
And this is the spotbugs eclipse config:
I can also provide a threaddump but I have to remove all class names and project names first.
Thanks, it might be possible Eclipse run it with several threads (I don't use Eclipse). That's interesting to know.
Can you please connect jconsole or similar (I use https://www.yourkit.com/) to look at the allocated memory, GC pauses etc?
Also, you have SpotBugs configured to run as an extra job, I'm sorry I don't know what it means. Does it spawn a new thread, JVM? What's the heap there?
GC can remove items from WeakHashMap but it should not create a deadlock, my guess is still full heap and GC trying to free a bit of memory.
For reference I'm testing a webapp with 2000 modules with 1500 jar files (600MB in class files) and the JVM consumes around 10GB of heap.
It is not a memory problem. Eclipse is started with 4GB max heap. Currently used are roughly 1.7GB. 4 Threads are hanging again in WeakHashMap.get(WeakHashMap.java:403). I triggered several GCs via Eclipse and jconsole but the threads are still hanging even after 1 hour.
I assume that the option "Run SpotBugs analysis as extra job (independent from build job)" leads to faster compile results. The build should be available and Spotbugs can run afterwards.
Thanks @mhnot, then the next step is to come up with a test to reproduce it /cc @h3xstream if he has any idea :)
I'm looking into SpotBugs code and they are not very well prepared for multi-threading as well. The solution here can be 1, to move the cache into a ThreadLocal if the separate threads are analyzing separate parts of application 2, synchronize access to the cache (or CopyOnWrite...) if the threads are sharing parts of application
fwiw: concurrent access to j.u.(Weak)HashMap
often manifests as an infinite loop in map.get()
.
I think the static superMap
cache is fundamentally problematic: Even if you make it thread-safe the problem is that it's still static.
This probably(?) means its lifecycle is bounded to the lifecycle of Eclipse itself. So when you change a class hierarchy - for example by adding or removing a super class - then this change will NOT be reflected in the superMap
cache. There is no cache invalidation after all.
In other words: The cache is assuming a class hierarchy cannot change during the lifetime of the cache. This is true e.g. when being executed from Maven. But it's probably not true when being executed from IDE.
There is a good chance it effects also other IDEs. Unless they create a new classloader for each analysis.
Moving the cache to thread-local could help, but you would have to clear it up before each analysis. Otherwise a thread re-use would also lead to a cache re-use and hence to the same issue with class hierarchy changes.
Just stumbled upon https://dowbecki.com/WeakHashMap-is-not-thread-safe/ where they identified the same problem, referencing also https://issues.jenkins.io/browse/JENKINS-6528
The recommendation is to avoid WeakHashMap in a multi-threaded environment completely. I'm working on the fix.
Environment
Problem
The find-security-bugs plugin for eclipse runs sometimes into a stucked thread problem with my project. Every now and then some threads are hanging at full CPU usage.
sample stacktrace:
I pulled the stacktraces many times and they are always hanging at "java.util.WeakHashMap.get(WeakHashMap.java:403)"
The problem seems to be caused by the usage of WeakHashMap which is not thread safe and some concurrent access.