ClassBasedBreakpoint.remove() is waiting on a lock that can be held by ClassBasedBreakpoint.isEnabled() for a long time. When ClassBasedBreakpoint.remove() is called in AWT thread, AWT is blocked until ClassBasedBreakpoint.isEnabled() finishes. This makes IDE unresponsive.
Perhaps should consider to remove the logic in ClassBasedBreakpoint.isEnabled() completely. It looks for explicitly disabled source roots not to submit breakpoints from them. There's very low chance this would be useful for anybody (why to have breakpoints in disabled sources anyway?), yet it potentially slows down everyone.
For reference, see issue #186345 - attachment deb2.nps (http://netbeans.org/bugzilla/attachment.cgi?id=99530) - where ClassBasedBreakpoint.isEnabled() takes 50 seconds, because it is waiting for filesystem.
In the profiler snapshot method
"protected boolean isEnabled(String sourcePath, String preferredSourceRoot)"
is called. This checks whether the breakpoint belongs to the first matched source root on the source path. This is necessary when there are two projects with identical sources. We must take breakpoints only from the project that is actually used for debugging.
I have to leave that code there, but I think that it does not have to be synchronized. It must not block AWT.
Fixed in changeset 172280 0358eba9bfc9
Integrated into 'main-golden', will be available in build *201006030001* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress)
Log: #186808 Synchronization is reduced so that we do not do expansive work under SOURCE_ROOT_LOCK, which can be acquired in AWT thread.