1 11 package org.eclipse.jdt.internal.debug.ui.monitors; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import java.util.Map ; 18 19 import org.eclipse.core.runtime.IAdaptable; 20 import org.eclipse.debug.core.DebugEvent; 21 import org.eclipse.debug.core.DebugPlugin; 22 import org.eclipse.debug.core.IDebugEventSetListener; 23 import org.eclipse.debug.core.model.IDebugElement; 24 import org.eclipse.debug.core.model.IThread; 25 import org.eclipse.jdt.debug.core.IJavaDebugTarget; 26 import org.eclipse.jdt.debug.core.IJavaObject; 27 import org.eclipse.jdt.debug.core.IJavaThread; 28 import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants; 29 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; 30 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPreferenceInitializer; 31 import org.eclipse.jface.preference.IPreferenceStore; 32 import org.eclipse.jface.util.IPropertyChangeListener; 33 import org.eclipse.jface.util.PropertyChangeEvent; 34 35 38 public class ThreadMonitorManager implements IDebugEventSetListener, IPropertyChangeListener { 39 40 private static ThreadMonitorManager fDefaultManager; 41 42 45 private HashMap fJavaMonitorThreads; 46 49 private HashMap fJavaMonitors; 50 51 private boolean fIsEnabled; 52 53 56 public static ThreadMonitorManager getDefault() { 57 if (fDefaultManager == null) { 58 fDefaultManager= new ThreadMonitorManager(); 59 } 60 return fDefaultManager; 61 } 62 63 private ThreadMonitorManager() { 64 fJavaMonitorThreads= new HashMap (); 65 fJavaMonitors= new HashMap (); 66 IPreferenceStore preferenceStore = JDIDebugUIPlugin.getDefault().getPreferenceStore(); 67 preferenceStore.addPropertyChangeListener(this); 68 fIsEnabled= preferenceStore.getBoolean(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO); 69 if (fIsEnabled) { 70 DebugPlugin.getDefault().addDebugEventListener(this); 71 } 72 } 73 74 77 public void handleDebugEvents(DebugEvent[] events) { 78 for (int i= 0; i < events.length; i++) { 79 DebugEvent debugEvent= events[i]; 80 Object eventSource= debugEvent.getSource(); 81 int eventKind= debugEvent.getKind(); 82 IJavaThread javaThread = null; 83 if (eventSource instanceof IAdaptable) { 84 IAdaptable adaptable = (IAdaptable)eventSource; 85 javaThread = (IJavaThread) adaptable.getAdapter(IJavaThread.class); 86 if (javaThread != null) { 87 switch (eventKind) { 88 case DebugEvent.SUSPEND: 89 case DebugEvent.RESUME: 90 if (debugEvent.getDetail() != DebugEvent.EVALUATION_IMPLICIT) { 92 handleSuspendResume(); 93 } 94 break; 95 case DebugEvent.TERMINATE: 96 handleThreadTerminate(javaThread); 98 break; 99 } 100 } else { 101 IJavaDebugTarget target = (IJavaDebugTarget) adaptable.getAdapter(IJavaDebugTarget.class); 102 if (target != null) { 103 switch (eventKind) { 104 case DebugEvent.SUSPEND: 105 case DebugEvent.RESUME: 106 if (debugEvent.getDetail() != DebugEvent.EVALUATION_IMPLICIT) { 108 handleSuspendResume(); 109 } 110 break; 111 case DebugEvent.TERMINATE: 112 handleDebugTargetTerminate(target); 114 break; 115 } 116 } 117 } 118 } 119 } 120 } 121 122 private void handleSuspendResume() { 123 JavaMonitorThread[] threads = getJavaMonitorThreads(); 124 for (int i = 0; i < threads.length; i++) { 125 threads[i].setToUpdate(); 126 } 127 DebugPlugin.getDefault().asyncExec(new RefreshAndDetectDeadlock()); 128 } 129 130 private void handleThreadTerminate(IJavaThread thread) { 131 synchronized(fJavaMonitorThreads) { 133 fJavaMonitorThreads.remove(thread); 134 } 135 } 136 137 private void handleDebugTargetTerminate(IJavaDebugTarget debugTarget) { 138 clean(fJavaMonitors, debugTarget); 140 clean(fJavaMonitorThreads, debugTarget); 141 } 142 143 private void clean(Map map, IJavaDebugTarget debugTarget) { 144 IDebugElement debugElements[] = null; 145 synchronized(map) { 146 debugElements = new IDebugElement[map.size()]; 147 debugElements = (IDebugElement[]) map.keySet().toArray(debugElements); 148 } 149 for(int i = 0; i < debugElements.length; ++i) { 150 if (debugElements[i].getDebugTarget().equals(debugTarget)) { 151 synchronized(map) { 152 map.remove(debugElements[i]); 153 } 154 } 155 } 156 } 157 158 161 protected JavaMonitorThread getJavaMonitorThread(IJavaThread thread, IThread originalThread) { 162 synchronized (fJavaMonitorThreads) { 163 JavaMonitorThread javaMonitorThread= (JavaMonitorThread) fJavaMonitorThreads.get(thread); 164 if (javaMonitorThread == null) { 165 javaMonitorThread= new JavaMonitorThread(thread, originalThread); 166 fJavaMonitorThreads.put(thread, javaMonitorThread); 167 DebugPlugin.getDefault().asyncExec(new DetectDeadlock()); 168 } else if (originalThread != null) { 169 javaMonitorThread.setOriginalThread(originalThread); 170 } 171 return javaMonitorThread; 172 } 173 } 174 175 178 protected JavaMonitor getJavaMonitor(IJavaObject monitor) { 179 synchronized (fJavaMonitors) { 180 JavaMonitor javaMonitor= (JavaMonitor) fJavaMonitors.get(monitor); 181 if (javaMonitor == null) { 182 javaMonitor= new JavaMonitor(monitor); 183 fJavaMonitors.put(monitor, javaMonitor); 184 } 185 return javaMonitor; 186 } 187 } 188 189 192 protected void removeJavaMonitor(JavaMonitor monitor) { 193 synchronized(fJavaMonitors) { 194 fJavaMonitors.remove(monitor.getMonitor()); 195 } 196 } 197 198 201 public JavaContendedMonitor getContendedMonitor(IThread thread) { 202 IJavaThread javaThread = (IJavaThread) thread.getAdapter(IJavaThread.class); 203 if (javaThread == null || !fIsEnabled || !((IJavaDebugTarget)javaThread.getDebugTarget()).supportsMonitorInformation()) { 204 return null; 205 } 206 return getJavaMonitorThread(javaThread, thread).getContendedMonitor(); 207 } 208 209 212 public JavaOwnedMonitor[] getOwnedMonitors(IThread thread) { 213 IJavaThread javaThread = (IJavaThread) thread.getAdapter(IJavaThread.class); 214 if (javaThread == null || !fIsEnabled || !((IJavaDebugTarget)javaThread.getDebugTarget()).supportsMonitorInformation()) { 215 return new JavaOwnedMonitor[0]; 216 } 217 return getJavaMonitorThread(javaThread, thread).getOwnedMonitors(); 218 } 219 220 224 class RefreshAndDetectDeadlock extends DetectDeadlock { 225 public void run() { 226 JavaMonitorThread[] threads= getJavaMonitorThreads(); 227 for (int i = 0; i < threads.length; i++) { 228 threads[i].refresh(); 229 } 230 super.run(); 231 } 232 } 233 234 class DetectDeadlock implements Runnable { 235 public void run() { 236 JavaMonitorThread[] threads= getJavaMonitorThreads(); 237 JavaMonitor[] monitors= getJavaMonitors(); 238 List inDeadlock= new ArrayList (); 239 for (int i = 0; i < threads.length; i++) { 240 JavaMonitorThread thread= threads[i]; 241 List threadStack= new ArrayList (); 242 List monitorStack= new ArrayList (); 243 while (thread != null) { 244 boolean isInDeadlock= false; 245 if (inDeadlock.contains(thread) || threadStack.contains(thread)) { 246 isInDeadlock= true; 247 } else { 248 JavaMonitor monitor = thread.getContendedMonitor0(); 249 if (monitor == null) { 250 thread= null; 251 } else if (inDeadlock.contains(monitor)) { 252 isInDeadlock= true; 253 } else { 254 threadStack.add(thread); 255 monitorStack.add(monitor); 256 thread= monitor.getOwningThread0(); 257 } 258 } 259 if (isInDeadlock) { 260 for (Iterator iter = threadStack.iterator(); iter.hasNext();) { 262 inDeadlock.add(iter.next()); 263 } 264 for (Iterator iter = monitorStack.iterator(); iter.hasNext();) { 265 inDeadlock.add(iter.next()); 266 } 267 thread= null; 268 } 269 } 270 } 271 for (int i = 0; i < threads.length; i++) { 272 JavaMonitorThread thread= threads[i]; 273 thread.setInDeadlock(inDeadlock.contains(thread)); 274 } 275 for (int i = 0; i < monitors.length; i++) { 276 JavaMonitor monitor= monitors[i]; 277 monitor.setInDeadlock(inDeadlock.contains(monitor)); 278 } 279 } 280 } 281 282 285 public void propertyChange(PropertyChangeEvent event) { 286 if (event.getProperty().equals(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO)) { 287 fIsEnabled= JDIDebugUIPreferenceInitializer.getBoolean(event); 288 if (fIsEnabled) { 289 DebugPlugin.getDefault().addDebugEventListener(this); 290 } else { 291 DebugPlugin.getDefault().removeDebugEventListener(this); 292 } 293 } 294 } 295 296 300 public boolean isInDeadlock(IThread thread) { 301 IJavaThread javaThread = (IJavaThread) thread.getAdapter(IJavaThread.class); 302 if (!fIsEnabled || !((IJavaDebugTarget)javaThread.getDebugTarget()).supportsMonitorInformation()) { 303 return false; 304 } 305 return getJavaMonitorThread(javaThread, thread).isInDeadlock(); 306 } 307 308 private JavaMonitor[] getJavaMonitors() { 309 synchronized(fJavaMonitors) { 310 JavaMonitor[] monitors = new JavaMonitor[fJavaMonitors.size()]; 311 return (JavaMonitor[]) fJavaMonitors.values().toArray(monitors); 312 } 313 } 314 315 private JavaMonitorThread[] getJavaMonitorThreads() { 316 synchronized(fJavaMonitorThreads) { 317 JavaMonitorThread[] threads = new JavaMonitorThread[fJavaMonitorThreads.size()]; 318 return (JavaMonitorThread[]) fJavaMonitorThreads.values().toArray(threads); 319 } 320 } 321 } 322 | Popular Tags |