Current threading model in JPDA debugger is not really clear. JPDADebuggerImpl.LOCK is mostly used to synchronize access
to JDI and resume/suspend actions. However, threads have their own synchronization (directly on the JPDAThreadImpl
object). Combining of these locks does not scale much and is not implemented everywhere to handle collisions of
VirtualMachine.resume() with actions on individual threads.
The access to the debuggee through JDI layer can be classified into different categories. Each category have read or
write access and concerns a specific thread or the whole debuggee VM. Therefore we can have a "read" or "write" access
with global impact (on whole VirtualMachine and all it's threads) and "read" or "write" access to a specific thread.
Read or write operations on specific thread should run concurrently with read or write operations on other threads.
But global write operation needs to be exclusive.
In order to accomplish this, ReadWriteLock can be introduced instead of the plain synchronize.
The solution is to introduce:
ReadWriteLock JPDADebuggerImpl.accessLock field
ReadWriteLock JPDAThreadImpl.accessLock field.
Acquisition of JPDAThreadImpl.accessLock.readLock() or JPDAThreadImpl.accessLock.writeLock() will also acquire
JPDADebuggerImpl.accessLock.readLock(). That assures that the VM global state can not be changed while invoking
operations on a thread.
Retrieval of thread state (like call stack, monitors, local variables, etc.) is performed under
Modification of thread state (like suspend/resume, method invocation) is performed under
Retrieval of VM global state is performed under JPDADebuggerImpl.accessLock.readLock().
Modification of VM global state is performed under JPDADebuggerImpl.accessLock.writeLock().
Since we need to retrieve the thread state information from the debugger.jpda.ui module as well, we need to put the
JPDAThreadImpl.accessLock.readLock() into the APIs in order to be able to synchronize the access on it.
Created attachment 75509 [details]
The proposed API change.
Please review this simple API change that helps with synchronization.
Instead of synchronize(JPDAThread instance) client code will use JPDAThread.getReadAccessLock().lock().
Thanks, I'm going to commit this simple change tomorrow COB.
The synchronized constructs are replaced with ReadWriteLock in changeset: 113877:7571a0a187b9
Also, in order to improve the threads management and prevent from threads proliferation, JavaEngineProvider creates an
RP of throughoutput 5, which is used for JDI communication. Changeset: 113878:18aae736efdb
To assure that we do not acquire the communication lock in AWT thread, assertion was added in changeset:
Integrated into 'main-golden', will be available in build *200901160201* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress)
Log: #156368 - Improve the threading model.
ReadWriteLock is introduced to synchronize the communication with the debuggee instead of the "synchronize" keyword.
Verified ... and Closing all issues resolved into NetBeans 6.7 and earlier.