| 1 12 package org.eclipse.jdt.internal.debug.core.model; 13 14 15 import java.util.ArrayList ; 16 import java.util.Collections ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Vector ; 20 21 import org.eclipse.core.runtime.CoreException; 22 import org.eclipse.core.runtime.IProgressMonitor; 23 import org.eclipse.core.runtime.IStatus; 24 import org.eclipse.core.runtime.MultiStatus; 25 import org.eclipse.core.runtime.Status; 26 import org.eclipse.core.runtime.jobs.ISchedulingRule; 27 import org.eclipse.core.runtime.jobs.Job; 28 import org.eclipse.debug.core.DebugEvent; 29 import org.eclipse.debug.core.DebugException; 30 import org.eclipse.debug.core.DebugPlugin; 31 import org.eclipse.debug.core.IStatusHandler; 32 import org.eclipse.debug.core.model.IBreakpoint; 33 import org.eclipse.debug.core.model.IStackFrame; 34 import org.eclipse.debug.core.model.ITerminate; 35 import org.eclipse.jdt.core.Signature; 36 import org.eclipse.jdt.debug.core.IEvaluationRunnable; 37 import org.eclipse.jdt.debug.core.IJavaBreakpoint; 38 import org.eclipse.jdt.debug.core.IJavaObject; 39 import org.eclipse.jdt.debug.core.IJavaStackFrame; 40 import org.eclipse.jdt.debug.core.IJavaThread; 41 import org.eclipse.jdt.debug.core.IJavaThreadGroup; 42 import org.eclipse.jdt.debug.core.IJavaValue; 43 import org.eclipse.jdt.debug.core.IJavaVariable; 44 import org.eclipse.jdt.debug.core.JDIDebugModel; 45 import org.eclipse.jdt.internal.debug.core.IJDIEventListener; 46 import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin; 47 import org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint; 48 49 import com.ibm.icu.text.MessageFormat; 50 import com.sun.jdi.BooleanValue; 51 import com.sun.jdi.ClassNotLoadedException; 52 import com.sun.jdi.ClassType; 53 import com.sun.jdi.Field; 54 import com.sun.jdi.IncompatibleThreadStateException; 55 import com.sun.jdi.IntegerValue; 56 import com.sun.jdi.InvalidStackFrameException; 57 import com.sun.jdi.InvalidTypeException; 58 import com.sun.jdi.InvocationException; 59 import com.sun.jdi.Location; 60 import com.sun.jdi.Method; 61 import com.sun.jdi.ObjectCollectedException; 62 import com.sun.jdi.ObjectReference; 63 import com.sun.jdi.ReferenceType; 64 import com.sun.jdi.StackFrame; 65 import com.sun.jdi.ThreadGroupReference; 66 import com.sun.jdi.ThreadReference; 67 import com.sun.jdi.VMDisconnectedException; 68 import com.sun.jdi.Value; 69 import com.sun.jdi.event.Event; 70 import com.sun.jdi.event.StepEvent; 71 import com.sun.jdi.request.EventRequest; 72 import com.sun.jdi.request.EventRequestManager; 73 import com.sun.jdi.request.StepRequest; 74 75 79 public class JDIThread extends JDIDebugElement implements IJavaThread { 80 81 84 private static final String JAVA_STRATUM_CONSTANT = "Java"; 86 89 private static final String MAIN_THREAD_GROUP = "main"; 93 public static final int SUSPEND_TIMEOUT= 161; 94 97 private ThreadReference fThread; 98 101 private String fPreviousName; 102 105 private List fStackFrames; 106 109 private ThreadGroupReference fThreadGroup; 110 113 private String fThreadGroupName; 114 119 private boolean fRefreshChildren = true; 120 124 private StepHandler fStepHandler= null; 125 128 private boolean fRunning; 129 132 private boolean fTerminated; 133 136 private boolean fSuspendedQuiet; 137 140 private boolean fIsSystemThread; 141 142 146 private boolean fIsDaemon = false; 147 148 153 private List fCurrentBreakpoints = new ArrayList (2); 154 159 private boolean fIsPerformingEvaluation= false; 160 private IEvaluationRunnable fEvaluationRunnable; 161 162 166 private boolean fEvaluationInterrupted = false; 167 168 172 private boolean fIsInvokingMethod = false; 173 178 private boolean fHonorBreakpoints= true; 179 185 private int fOriginalStepKind; 186 189 private Location fOriginalStepLocation; 190 197 private int fOriginalStepStackDepth; 198 199 202 private boolean fIsSuspending= false; 203 206 private boolean fIsEvaluatingConditionalBreakpoint= false; 207 208 private ThreadJob fAsyncJob; 209 210 private ThreadJob fRunningAsyncJob; 211 212 221 public JDIThread(JDIDebugTarget target, ThreadReference thread) throws ObjectCollectedException { 222 super(target); 223 setUnderlyingThread(thread); 224 initialize(); 225 } 226 227 237 protected void initialize() throws ObjectCollectedException { 238 fStackFrames= new ArrayList (); 239 try { 241 determineIfSystemThread(); 242 } catch (DebugException e) { 243 Throwable underlyingException= e.getStatus().getException(); 244 if (underlyingException instanceof VMDisconnectedException) { 245 disconnected(); 249 return; 250 } 251 if (underlyingException instanceof ObjectCollectedException) { 252 throw (ObjectCollectedException)underlyingException; 253 } 254 logError(e); 255 } 256 257 try { 258 determineIfDaemonThread(); 259 } catch (DebugException e) { 260 Throwable underlyingException= e.getStatus().getException(); 261 if (underlyingException instanceof VMDisconnectedException) { 262 disconnected(); 266 return; 267 } 268 logError(e); 269 } 270 271 try { 272 ThreadGroupReference group = getUnderlyingThreadGroup(); 273 if (group != null) { 275 getJavaDebugTarget().addThreadGroup(group); 276 } 277 } catch (DebugException e1) { 278 } 279 280 setTerminated(false); 282 setRunning(false); 283 try { 284 if (fThread.status() == ThreadReference.THREAD_STATUS_UNKNOWN) { 286 setRunning(true); 287 return; 288 } 289 } catch (VMDisconnectedException e) { 290 disconnected(); 291 return; 292 } catch (ObjectCollectedException e){ 293 throw e; 294 } catch (RuntimeException e) { 295 logError(e); 296 } 297 298 try { 299 boolean suspended = fThread.isSuspended(); 300 if (suspended) { 301 suspended = getBreakpoints().length > 0; 307 } 308 setRunning(!suspended); 309 } catch (VMDisconnectedException e) { 310 disconnected(); 311 return; 312 } catch (ObjectCollectedException e){ 313 throw e; 314 } catch (RuntimeException e) { 315 logError(e); 316 } 317 } 318 319 323 protected void addCurrentBreakpoint(IBreakpoint bp) { 324 fCurrentBreakpoints.add(bp); 325 } 326 327 332 protected void removeCurrentBreakpoint(IBreakpoint bp) { 333 fCurrentBreakpoints.remove(bp); 334 } 335 336 339 public synchronized IBreakpoint[] getBreakpoints() { 340 return (IBreakpoint[])fCurrentBreakpoints.toArray(new IBreakpoint[fCurrentBreakpoints.size()]); 341 } 342 343 346 public boolean canResume() { 347 return isSuspended() && !isSuspendedQuiet() && (!isPerformingEvaluation() || isInvokingMethod()); 348 } 349 350 353 public boolean canSuspend() { 354 return !isSuspended() || isSuspendedQuiet() || (isPerformingEvaluation() && !isInvokingMethod()); 355 } 356 357 360 public boolean canTerminate() { 361 return getDebugTarget().canTerminate(); 362 } 363 364 367 public boolean canStepInto() { 368 return canStep(); 369 } 370 371 374 public boolean canStepOver() { 375 return canStep(); 376 } 377 378 381 public boolean canStepReturn() { 382 return canStep(); 383 } 384 385 392 protected boolean canStep() { 393 try { 394 return isSuspended() 395 && !isSuspendedQuiet() 396 && (!isPerformingEvaluation() || isInvokingMethod()) 397 && !isStepping() 398 && getTopStackFrame() != null 399 && !getJavaDebugTarget().isPerformingHotCodeReplace(); 400 } catch (DebugException e) { 401 return false; 402 } 403 } 404 405 415 protected void determineIfSystemThread() throws DebugException { 416 fIsSystemThread= false; 417 ThreadGroupReference tgr= getUnderlyingThreadGroup(); 418 fIsSystemThread = tgr != null; 419 while (tgr != null) { 420 String tgn= null; 421 try { 422 tgn= tgr.name(); 423 tgr= tgr.parent(); 424 } catch (UnsupportedOperationException e) { 425 fIsSystemThread = false; 426 break; 427 } catch (RuntimeException e) { 428 targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIThread_exception_determining_if_system_thread, new String [] {e.toString()}), e); 429 return; 432 } 433 if (tgn != null && tgn.equals(MAIN_THREAD_GROUP)) { 434 fIsSystemThread= false; 435 break; 436 } 437 } 438 } 439 440 445 protected void determineIfDaemonThread() throws DebugException { 446 fIsDaemon = false; 447 try { 448 ReferenceType referenceType = getUnderlyingThread().referenceType(); 449 Field field = referenceType.fieldByName("daemon"); if (field == null) { 451 field = referenceType.fieldByName("isDaemon"); } 453 if (field != null) { 454 if (field.signature().equals(Signature.SIG_BOOLEAN)) { 455 Value value = getUnderlyingThread().getValue(field); 456 if (value instanceof BooleanValue) { 457 fIsDaemon = ((BooleanValue)value).booleanValue(); 458 } 459 } 460 } 461 } 462 catch(ObjectCollectedException oce) {} 463 catch (RuntimeException e) { 464 targetRequestFailed(JDIDebugModelMessages.JDIThread_47, e); 465 } 466 } 467 468 473 public synchronized IStackFrame[] getStackFrames() throws DebugException { 474 if (isSuspendedQuiet()) { 475 return new IStackFrame[0]; 476 } 477 List list = computeStackFrames(); 478 return (IStackFrame[])list.toArray(new IStackFrame[list.size()]); 479 } 480 481 487 protected synchronized List computeStackFrames(boolean refreshChildren) throws DebugException { 488 if (isSuspended()) { 489 if (isTerminated()) { 490 fStackFrames.clear(); 491 } else if (refreshChildren) { 492 List frames = getUnderlyingFrames(); 493 int oldSize = fStackFrames.size(); 494 int newSize = frames.size(); 495 int discard = oldSize - newSize; for (int i = 0; i < discard; i++) { 497 JDIStackFrame invalid = (JDIStackFrame) fStackFrames.remove(0); 498 invalid.bind(null, -1); 499 } 500 int newFrames = newSize - oldSize; int depth = oldSize; 502 for (int i = newFrames - 1; i >= 0; i--) { 503 fStackFrames.add(0, new JDIStackFrame(this, (StackFrame) frames.get(i), depth)); 504 depth++; 505 } 506 int numToRebind = Math.min(newSize, oldSize); int offset = newSize - 1; 508 for (depth = 0; depth < numToRebind; depth++) { 509 JDIStackFrame oldFrame = (JDIStackFrame) fStackFrames.get(offset); 510 StackFrame frame = (StackFrame) frames.get(offset); 511 JDIStackFrame newFrame = oldFrame.bind(frame, depth); 512 if (newFrame != oldFrame) { 513 fStackFrames.set(offset, newFrame); 514 } 515 offset--; 516 } 517 518 519 } 520 fRefreshChildren = false; 521 } else { 522 return Collections.EMPTY_LIST; 523 } 524 return fStackFrames; 525 } 526 527 555 public synchronized List computeStackFrames() throws DebugException { 556 return computeStackFrames(fRefreshChildren); 557 } 558 559 568 public List computeNewStackFrames() throws DebugException { 569 return computeStackFrames(true); 570 } 571 572 private List getUnderlyingFrames() throws DebugException { 573 if (!isSuspended()) { 574 requestFailed(JDIDebugModelMessages.JDIThread_Unable_to_retrieve_stack_frame___thread_not_suspended__1, null, IJavaThread.ERR_THREAD_NOT_SUSPENDED); 578 } 579 try { 580 return fThread.frames(); 581 } catch (IncompatibleThreadStateException e) { 582 requestFailed(JDIDebugModelMessages.JDIThread_Unable_to_retrieve_stack_frame___thread_not_suspended__1, e, IJavaThread.ERR_THREAD_NOT_SUSPENDED); 583 } catch (RuntimeException e) { 584 targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIThread_exception_retrieving_stack_frames_2, new String [] {e.toString()}), e); 585 } catch (InternalError e) { 586 targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIThread_exception_retrieving_stack_frames_2, new String [] {e.toString()}), e); 587 } 588 return null; 591 } 592 593 606 protected int getUnderlyingFrameCount() throws DebugException { 607 try { 608 return fThread.frameCount(); 609 } catch (RuntimeException e) { 610 targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIThread_exception_retrieving_frame_count, new String [] {e.toString()}), e); 611 } catch (IncompatibleThreadStateException e) { 612 requestFailed(MessageFormat.format(JDIDebugModelMessages.JDIThread_exception_retrieving_frame_count, new String [] {e.toString()}), e, IJavaThread.ERR_THREAD_NOT_SUSPENDED); 613 } 614 return -1; 617 } 618 619 622 public void runEvaluation(IEvaluationRunnable evaluation, IProgressMonitor monitor, int evaluationDetail, boolean hitBreakpoints) throws DebugException { 623 if (isPerformingEvaluation()) { 624 requestFailed(JDIDebugModelMessages.JDIThread_Cannot_perform_nested_evaluations, null, IJavaThread.ERR_NESTED_METHOD_INVOCATION); } 626 627 if (!canRunEvaluation()) { 628 requestFailed(JDIDebugModelMessages.JDIThread_Evaluation_failed___thread_not_suspended, null, IJavaThread.ERR_THREAD_NOT_SUSPENDED); 629 } 630 631 fIsPerformingEvaluation = true; 632 fEvaluationRunnable= evaluation; 633 fHonorBreakpoints= hitBreakpoints; 634 fireResumeEvent(evaluationDetail); 635 IBreakpoint[] breakpoints = getBreakpoints(); 637 ISchedulingRule rule = null; 638 if (evaluationDetail == DebugEvent.EVALUATION_IMPLICIT) { 639 rule = getThreadRule(); 640 } 641 try { 642 if (rule != null) { 643 Job.getJobManager().beginRule(rule, monitor); 644 } 645 if (monitor == null || !monitor.isCanceled()) { 646 evaluation.run(this, monitor); 647 } 648 } catch (DebugException e) { 649 throw e; 650 } finally { 651 if (rule != null) { 652 Job.getJobManager().endRule(rule); 653 } 654 fIsPerformingEvaluation = false; 655 fEvaluationRunnable= null; 656 fHonorBreakpoints= true; 657 if (getBreakpoints().length == 0 && breakpoints.length > 0) { 658 for (int i = 0; i < breakpoints.length; i++) { 659 addCurrentBreakpoint(breakpoints[i]); 660 } 661 } 662 fireSuspendEvent(evaluationDetail); 663 if (fEvaluationInterrupted && (fAsyncJob == null || fAsyncJob.isEmpty()) && (fRunningAsyncJob == null || fRunningAsyncJob.isEmpty())) { 664 fEvaluationInterrupted = false; 670 fireChangeEvent(DebugEvent.CONTENT); 671 } 672 } 673 } 674 675 682 protected boolean canRunEvaluation() { 683 try { 685 return isSuspendedQuiet() || (isSuspended() 686 && !(isPerformingEvaluation() || isInvokingMethod()) 687 && !isStepping() 688 && getTopStackFrame() != null 689 && !getJavaDebugTarget().isPerformingHotCodeReplace()); 690 } catch (DebugException e) { 691 return false; 692 } 693 } 694 695 698 public void queueRunnable(Runnable evaluation) { 699 if (fAsyncJob == null) { 700 fAsyncJob= new ThreadJob(this); 701 } 702 fAsyncJob.addRunnable(evaluation); 703 } 704 705 708 public void terminateEvaluation() throws DebugException { 709 if (canTerminateEvaluation()) { 710 ((ITerminate) fEvaluationRunnable).terminate(); 711 } 712 } 713 714 717 public boolean canTerminateEvaluation() { 718 return fEvaluationRunnable instanceof ITerminate; 719 } 720 721 771 protected Value invokeMethod(ClassType receiverClass, ObjectReference receiverObject, Method method, List args, boolean invokeNonvirtual) throws DebugException { 772 if (receiverClass != null && receiverObject != null) { 773 throw new IllegalArgumentException (JDIDebugModelMessages.JDIThread_can_only_specify_one_receiver_for_a_method_invocation); 774 } 775 Value result= null; 776 int timeout= getRequestTimeout(); 777 try { 778 synchronized (this) { 783 if (!isSuspended()) { 784 requestFailed(JDIDebugModelMessages.JDIThread_Evaluation_failed___thread_not_suspended, null, IJavaThread.ERR_THREAD_NOT_SUSPENDED); 785 } 786 if (isInvokingMethod()) { 787 requestFailed(JDIDebugModelMessages.JDIThread_Cannot_perform_nested_evaluations, null, IJavaThread.ERR_NESTED_METHOD_INVOCATION); 788 } 789 setRequestTimeout(Integer.MAX_VALUE); 791 setRunning(true); 792 setInvokingMethod(true); 793 } 794 preserveStackFrames(); 795 int flags= ClassType.INVOKE_SINGLE_THREADED; 796 if (invokeNonvirtual) { 797 flags |= ObjectReference.INVOKE_NONVIRTUAL; 799 } 800 if (receiverClass == null) { 801 result= receiverObject.invokeMethod(fThread, method, args, flags); 802 } else { 803 result= receiverClass.invokeMethod(fThread, method, args, flags); 804 } 805 } catch (InvalidTypeException e) { 806 invokeFailed(e, timeout); 807 } catch (ClassNotLoadedException e) { 808 invokeFailed(e, timeout); 809 } catch (IncompatibleThreadStateException e) { 810 invokeFailed(JDIDebugModelMessages.JDIThread_Thread_must_be_suspended_by_step_or_breakpoint_to_perform_method_invocation_1, IJavaThread.ERR_INCOMPATIBLE_THREAD_STATE, e, timeout); 811 } catch (InvocationException e) { 812 invokeFailed(e, timeout); 813 } catch (RuntimeException e) { 814 invokeFailed(e, timeout); 815 }
|