1 19 20 package org.netbeans.modules.debugger.jpda.models; 21 22 import com.sun.jdi.AbsentInformationException; 23 import com.sun.jdi.IncompatibleThreadStateException; 24 import com.sun.jdi.InvalidStackFrameException; 25 import com.sun.jdi.ObjectCollectedException; 26 import com.sun.jdi.ObjectReference; 27 import com.sun.jdi.StackFrame; 28 import com.sun.jdi.ThreadGroupReference; 29 import com.sun.jdi.ThreadReference; 30 import com.sun.jdi.VMDisconnectedException; 31 import java.beans.PropertyChangeListener ; 32 import java.beans.PropertyChangeSupport ; 33 import java.util.ArrayList ; 34 35 import java.util.List ; 36 37 import org.netbeans.api.debugger.jpda.CallStackFrame; 38 import org.netbeans.api.debugger.jpda.JPDAThread; 39 import org.netbeans.api.debugger.jpda.JPDAThreadGroup; 40 import org.netbeans.api.debugger.jpda.ObjectVariable; 41 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl; 42 import org.netbeans.spi.debugger.jpda.EditorContext; 43 import org.netbeans.spi.debugger.jpda.EditorContext.Operation; 44 import org.netbeans.spi.viewmodel.UnknownTypeException; 45 46 47 50 public final class JPDAThreadImpl implements JPDAThread { 51 52 55 public static final String PROP_SUSPENDED = "suspended"; 56 57 private ThreadReference threadReference; 58 private JPDADebuggerImpl debugger; 59 private boolean suspended; 60 private int suspendCount; 61 private Operation currentOperation; 62 private List <Operation> lastOperations; 63 private boolean doKeepLastOperations; 64 private ReturnVariableImpl returnVariable; 65 private PropertyChangeSupport pch = new PropertyChangeSupport (this); 66 private CallStackFrame[] cachedFrames; 67 private int cachedFramesFrom = -1; 68 private int cachedFramesTo = -1; 69 private Object cachedFramesLock = new Object (); 70 71 public JPDAThreadImpl ( 72 ThreadReference threadReference, 73 JPDADebuggerImpl debugger 74 ) { 75 this.threadReference = threadReference; 76 this.debugger = debugger; 77 suspended = threadReference.isSuspended(); 78 suspendCount = threadReference.suspendCount(); 79 } 80 81 86 public String getName () { 87 try { 88 return threadReference.name (); 89 } catch (ObjectCollectedException ex) { 90 return ""; 91 } catch (VMDisconnectedException ex) { 92 return ""; 93 } 94 } 95 96 101 public JPDAThreadGroup getParentThreadGroup () { 102 try { 103 ThreadGroupReference tgr = threadReference.threadGroup (); 104 if (tgr == null) return null; 105 return debugger.getThreadGroup(tgr); 106 } catch (ObjectCollectedException ex) { 107 return null; 108 } catch (VMDisconnectedException ex) { 109 return null; 110 } 111 } 112 113 122 public int getLineNumber (String stratum) { 123 try { 124 if (threadReference.frameCount () < 1) return -1; 125 return threadReference.frame (0).location ().lineNumber (stratum); 126 } catch (ObjectCollectedException ex) { 127 } catch (InvalidStackFrameException ex) { 128 } catch (IncompatibleThreadStateException ex) { 129 } catch (VMDisconnectedException ex) { 130 } 131 return -1; 132 } 133 134 public synchronized Operation getCurrentOperation() { 135 return currentOperation; 136 } 137 138 public synchronized void setCurrentOperation(Operation operation) { this.currentOperation = operation; 140 } 141 142 public synchronized List <Operation> getLastOperations() { 143 return lastOperations; 144 } 145 146 public synchronized void addLastOperation(Operation operation) { 147 if (lastOperations == null) { 148 lastOperations = new ArrayList <Operation>(); 149 } 150 lastOperations.add(operation); 151 } 152 153 public synchronized void clearLastOperations() { 154 lastOperations = null; 155 } 156 157 public synchronized void keepLastOperationsUponResume() { 158 doKeepLastOperations = true; 159 } 160 161 162 167 public int getState () { 168 try { 169 return threadReference.status (); 170 } catch (ObjectCollectedException ex) { 171 } catch (VMDisconnectedException ex) { 172 } 173 return STATE_UNKNOWN; 174 } 175 176 181 public synchronized boolean isSuspended () { 182 return suspended; 183 } 184 185 190 public boolean isThreadSuspended () { 191 try { 192 return threadReference.isSuspended (); 193 } catch (ObjectCollectedException ex) { 194 } catch (VMDisconnectedException ex) { 195 } 196 return false; 197 } 198 199 204 public String getClassName () { 205 try { 206 if (threadReference.frameCount () < 1) return ""; 207 return threadReference.frame (0).location ().declaringType ().name (); 208 } catch (ObjectCollectedException ex) { 209 } catch (InvalidStackFrameException ex) { 210 } catch (IncompatibleThreadStateException ex) { 211 } catch (VMDisconnectedException ex) { 212 } 213 return ""; 214 } 215 216 221 public String getMethodName () { 222 try { 223 if (threadReference.frameCount () < 1) return ""; 224 return threadReference.frame (0).location ().method ().name (); 225 } catch (ObjectCollectedException ex) { 226 } catch (InvalidStackFrameException ex) { 227 } catch (IncompatibleThreadStateException ex) { 228 } catch (VMDisconnectedException ex) { 229 } 230 return ""; 231 } 232 233 238 public String getSourceName (String stratum) throws AbsentInformationException { 239 try { 240 if (threadReference.frameCount () < 1) return ""; 241 return threadReference.frame (0).location ().sourceName (stratum); 242 } catch (ObjectCollectedException ex) { 243 } catch (InvalidStackFrameException ex) { 244 } catch (IncompatibleThreadStateException ex) { 245 } catch (VMDisconnectedException ex) { 246 } 247 return ""; 248 } 249 250 255 public String getSourcePath (String stratum) 256 throws AbsentInformationException { 257 try { 258 if (threadReference.frameCount () < 1) return ""; 259 return threadReference.frame (0).location ().sourcePath (stratum); 260 } catch (ObjectCollectedException ex) { 261 } catch (InvalidStackFrameException ex) { 262 } catch (IncompatibleThreadStateException ex) { 263 } catch (VMDisconnectedException ex) { 264 } 265 return ""; 266 } 267 268 279 public CallStackFrame[] getCallStack () throws AbsentInformationException { 280 return getCallStack (0, getStackDepth ()); 281 } 282 283 private Object lastBottomSF; 284 285 298 public CallStackFrame[] getCallStack (int from, int to) 299 throws AbsentInformationException { 300 try { 301 int max = threadReference.frameCount(); 302 from = Math.min(from, max); 303 to = Math.min(to, max); 304 if (to - from > 1) { 305 synchronized (cachedFramesLock) { 306 if (from == cachedFramesFrom && to == cachedFramesTo) { 307 return cachedFrames; 308 } 309 } 310 } 311 List l = threadReference.frames (from, to - from); 312 int n = l.size(); 313 CallStackFrame[] frames = new CallStackFrame[n]; 314 for (int i = 0; i < n; i++) { 315 frames[i] = new CallStackFrameImpl((StackFrame) l.get(i), from + i, debugger); 316 if (from == 0 && i == 0 && currentOperation != null) { 317 ((CallStackFrameImpl) frames[i]).setCurrentOperation(currentOperation); 318 } 319 } 320 if (to - from > 1) { 321 synchronized (cachedFramesLock) { 322 cachedFrames = frames; 323 cachedFramesFrom = from; 324 cachedFramesTo = to; 325 } 326 } 327 return frames; 328 } catch (IncompatibleThreadStateException ex) { 329 AbsentInformationException aiex = new AbsentInformationException(ex.getLocalizedMessage()); 330 aiex.initCause(ex); 331 throw aiex; 332 } catch (ObjectCollectedException ocex) { 333 AbsentInformationException aiex = new AbsentInformationException(ocex.getLocalizedMessage()); 334 aiex.initCause(ocex); 335 throw aiex; 336 } catch (VMDisconnectedException ex) { 337 return new CallStackFrame [0]; 338 } 339 } 340 341 private void cleanCachedFrames() { 342 synchronized (cachedFramesLock) { 343 cachedFrames = null; 344 cachedFramesFrom = -1; 345 cachedFramesTo = -1; 346 } 347 } 348 349 354 public int getStackDepth () { 355 try { 356 return threadReference.frameCount (); 357 } catch (ObjectCollectedException ex) { 358 } catch (IncompatibleThreadStateException e) { 359 } 360 return 0; 361 } 362 363 public void popFrames(StackFrame sf) throws IncompatibleThreadStateException { 364 threadReference.popFrames(sf); 365 cleanCachedFrames(); 366 setReturnVariable(null); } 368 369 372 public void suspend () { 373 Boolean suspendedToFire = null; 374 synchronized (this) { 375 try { 376 if (!isSuspended ()) { 377 threadReference.suspend (); 378 suspendedToFire = Boolean.TRUE; 379 suspendCount++; 380 } 381 suspended = true; 382 } catch (ObjectCollectedException ex) { 383 } catch (VMDisconnectedException ex) { 384 } 385 } 386 if (suspendedToFire != null) { 387 pch.firePropertyChange(PROP_SUSPENDED, 388 Boolean.valueOf(!suspendedToFire.booleanValue()), 389 suspendedToFire); 390 } 391 } 392 393 396 public void resume () { 397 if (this == debugger.getCurrentThread()) { 398 boolean can = debugger.currentThreadToBeResumed(); 399 if (!can) return ; 400 } 401 Boolean suspendedToFire = null; 402 synchronized (this) { 403 setReturnVariable(null); setCurrentOperation(null); 405 if (doKeepLastOperations) { 406 doKeepLastOperations = false; 407 } else { 408 clearLastOperations(); 409 } 410 try { 411 if (isSuspended ()) { 412 int count = threadReference.suspendCount (); 413 while (count > 0) { 414 threadReference.resume (); count--; 415 } 416 suspendedToFire = Boolean.FALSE; 417 } 418 suspendCount = 0; 419 suspended = false; 420 } catch (ObjectCollectedException ex) { 421 } catch (VMDisconnectedException ex) { 422 } 423 } 424 cleanCachedFrames(); 425 if (suspendedToFire != null) { 426 pch.firePropertyChange(PROP_SUSPENDED, 427 Boolean.valueOf(!suspendedToFire.booleanValue()), 428 suspendedToFire); 429 } 430 } 431 432 public void notifyToBeResumed() { 433 notifyToBeRunning(true, true); 434 } 435 436 private void notifyToBeRunning(boolean clearVars, boolean resumed) { 437 Boolean suspendedToFire = null; 438 synchronized (this) { 439 if (resumed && (--suspendCount > 0)) return ; 440 suspendCount = 0; 441 if (clearVars) { 442 setCurrentOperation(null); 443 setReturnVariable(null); if (doKeepLastOperations) { 445 doKeepLastOperations = false; 446 } else { 447 clearLastOperations(); 448 } 449 } 450 if (suspended) { 451 suspended = false; 452 suspendedToFire = Boolean.FALSE; 453 } 454 } 455 cleanCachedFrames(); 456 if (suspendedToFire != null) { 457 pch.firePropertyChange(PROP_SUSPENDED, 458 Boolean.valueOf(!suspendedToFire.booleanValue()), 459 suspendedToFire); 460 } 461 } 462 463 public void notifySuspended() { 464 Boolean suspendedToFire = null; 465 synchronized (this) { 466 suspendCount = threadReference.suspendCount(); 467 if (!suspended && isThreadSuspended()) { 468 suspended = true; 469 suspendedToFire = Boolean.TRUE; 470 } 471 } 472 if (suspendedToFire != null) { 473 pch.firePropertyChange(PROP_SUSPENDED, 474 Boolean.valueOf(!suspendedToFire.booleanValue()), 475 suspendedToFire); 476 } 477 } 478 479 public void notifyMethodInvoking() { 480 notifyToBeRunning(false, false); 481 } 482 483 public void notifyMethodInvokeDone() { 484 notifySuspended(); 485 } 486 487 public void interrupt() { 488 try { 489 if (isSuspended ()) return; 490 threadReference.interrupt(); 491 } catch (ObjectCollectedException ex) { 492 } catch (VMDisconnectedException ex) { 493 } 494 } 495 496 501 public void makeCurrent () { 502 debugger.setCurrentThread (this); 503 } 504 505 510 public ObjectVariable getContendedMonitor () { 511 try { 512 ObjectReference or; 513 synchronized (this) { 514 if (!isSuspended()) return null; 515 if ("DestroyJavaVM".equals(threadReference.name())) { 516 return null; 518 } 519 or = threadReference.currentContendedMonitor (); 520 } 521 if (or == null) return null; 522 return new ThisVariable (debugger, or, ""); 523 } catch (ObjectCollectedException ex) { 524 } catch (IncompatibleThreadStateException e) { 525 } catch (UnsupportedOperationException e) { 526 } 528 return null; 529 } 530 531 536 public ObjectVariable[] getOwnedMonitors () { 537 try { 538 List l; 539 synchronized (this) { 540 if (!isSuspended()) return new ObjectVariable [0]; 541 if ("DestroyJavaVM".equals(threadReference.name())) { 542 return new ObjectVariable[0]; 544 } 545 l = threadReference.ownedMonitors (); 546 } 547 int i, k = l.size (); 548 ObjectVariable[] vs = new ObjectVariable [k]; 549 for (i = 0; i < k; i++) { 550 vs [i] = new ThisVariable (debugger, (ObjectReference) l.get (i), ""); 551 } 552 return vs; 553 } catch (ObjectCollectedException ex) { 554 } catch (IncompatibleThreadStateException e) { 555 } catch (UnsupportedOperationException e) { 556 } 557 return new ObjectVariable [0]; 558 } 559 560 public ThreadReference getThreadReference () { 561 return threadReference; 562 } 563 564 public synchronized ReturnVariableImpl getReturnVariable() { 565 return returnVariable; 566 } 567 568 public synchronized void setReturnVariable(ReturnVariableImpl returnVariable) { 569 this.returnVariable = returnVariable; 570 } 571 572 public void addPropertyChangeListener(PropertyChangeListener l) { 573 pch.addPropertyChangeListener(l); 574 } 575 576 public void removePropertyChangeListener(PropertyChangeListener l) { 577 pch.removePropertyChangeListener(l); 578 } 579 580 private void fireSuspended(boolean suspended) { 581 pch.firePropertyChange(PROP_SUSPENDED, 582 Boolean.valueOf(!suspended), Boolean.valueOf(suspended)); 583 } 584 585 } 586 | Popular Tags |