001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdi.internal;
011:
012: import java.io.ByteArrayOutputStream;
013: import java.io.DataInputStream;
014: import java.io.DataOutputStream;
015: import java.io.IOException;
016: import java.lang.reflect.Field;
017: import java.lang.reflect.Modifier;
018: import java.util.ArrayList;
019: import java.util.HashMap;
020: import java.util.List;
021: import java.util.Map;
022:
023: import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
024: import org.eclipse.jdi.internal.jdwp.JdwpID;
025: import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
026: import org.eclipse.jdi.internal.jdwp.JdwpThreadID;
027:
028: import com.ibm.icu.text.MessageFormat;
029: import com.sun.jdi.ClassNotLoadedException;
030: import com.sun.jdi.IncompatibleThreadStateException;
031: import com.sun.jdi.InternalException;
032: import com.sun.jdi.InvalidStackFrameException;
033: import com.sun.jdi.InvalidTypeException;
034: import com.sun.jdi.NativeMethodException;
035: import com.sun.jdi.ObjectCollectedException;
036: import com.sun.jdi.ObjectReference;
037: import com.sun.jdi.StackFrame;
038: import com.sun.jdi.ThreadGroupReference;
039: import com.sun.jdi.ThreadReference;
040: import com.sun.jdi.VMCannotBeModifiedException;
041: import com.sun.jdi.VMDisconnectedException;
042: import com.sun.jdi.Value;
043:
044: /**
045: * This class implements the corresponding interfaces
046: * declared by the JDI specification. See the com.sun.jdi package
047: * for more information.
048: *
049: */
050: public class ThreadReferenceImpl extends ObjectReferenceImpl implements
051: ThreadReference, org.eclipse.jdi.hcr.ThreadReference {
052: /** ThreadStatus Constants. */
053: public static final int JDWP_THREAD_STATUS_ZOMBIE = 0;
054: public static final int JDWP_THREAD_STATUS_RUNNING = 1;
055: public static final int JDWP_THREAD_STATUS_SLEEPING = 2;
056: public static final int JDWP_THREAD_STATUS_MONITOR = 3;
057: public static final int JDWP_THREAD_STATUS_WAIT = 4;
058:
059: /** SuspendStatus Constants. */
060: public static final int SUSPEND_STATUS_SUSPENDED = 0x01;
061:
062: /** Mapping of command codes to strings. */
063: private static Map fgThreadStatusMap = null;
064:
065: /** Map with Strings for flag bits. */
066: private static String[] fgSuspendStatusStrings = null;
067:
068: /** JDWP Tag. */
069: protected static final byte tag = JdwpID.THREAD_TAG;
070:
071: /** Is thread currently at a breakpoint? */
072: private boolean fIsAtBreakpoint = false;
073:
074: /**
075: * The cached thread group. A thread's thread group cannot be changed.
076: */
077: private ThreadGroupReferenceImpl fThreadGroup = null;
078:
079: /**
080: * Creates new ThreadReferenceImpl.
081: */
082: public ThreadReferenceImpl(VirtualMachineImpl vmImpl,
083: JdwpThreadID threadID) {
084: super ("ThreadReference", vmImpl, threadID); //$NON-NLS-1$
085: }
086:
087: /**
088: * Sets at breakpoint flag.
089: */
090: public void setIsAtBreakpoint() {
091: fIsAtBreakpoint = true;
092: }
093:
094: /**
095: * Reset flags that can be set when event occurs.
096: */
097: public void resetEventFlags() {
098: fIsAtBreakpoint = false;
099: }
100:
101: /**
102: * @returns Value tag.
103: */
104: public byte getTag() {
105: return tag;
106: }
107:
108: /**
109: * @returns Returns an ObjectReference for the monitor, if any, for which this thread is currently waiting.
110: */
111: public ObjectReference currentContendedMonitor()
112: throws IncompatibleThreadStateException {
113: if (!virtualMachine().canGetCurrentContendedMonitor()) {
114: throw new UnsupportedOperationException();
115: }
116: // Note that this information should not be cached.
117: initJdwpRequest();
118: try {
119: JdwpReplyPacket replyPacket = requestVM(
120: JdwpCommandPacket.TR_CURRENT_CONTENDED_MONITOR,
121: this );
122: switch (replyPacket.errorCode()) {
123: case JdwpReplyPacket.INVALID_THREAD:
124: throw new ObjectCollectedException();
125: case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
126: throw new IncompatibleThreadStateException(
127: JDIMessages.ThreadReferenceImpl_Thread_was_not_suspended_1);
128: }
129: defaultReplyErrorHandler(replyPacket.errorCode());
130:
131: DataInputStream replyData = replyPacket.dataInStream();
132: ObjectReference result = ObjectReferenceImpl
133: .readObjectRefWithTag(this , replyData);
134: return result;
135: } catch (IOException e) {
136: defaultIOExceptionHandler(e);
137: return null;
138: } finally {
139: handledJdwpRequest();
140: }
141: }
142:
143: /**
144: * @see com.sun.jdi.ThreadReference#forceEarlyReturn(com.sun.jdi.Value)
145: * @since 3.3
146: */
147: public void forceEarlyReturn(Value value)
148: throws InvalidTypeException, ClassNotLoadedException,
149: IncompatibleThreadStateException {
150: if (!virtualMachineImpl().canBeModified()) {
151: throw new VMCannotBeModifiedException(
152: JDIMessages.ThreadReferenceImpl_vm_read_only);
153: }
154: initJdwpRequest();
155: ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
156: DataOutputStream dataOutStream = new DataOutputStream(
157: byteOutStream);
158: try {
159: write(this , dataOutStream);
160: ((ValueImpl) value).writeWithTag((ValueImpl) value,
161: dataOutStream);
162: JdwpReplyPacket reply = requestVM(
163: JdwpCommandPacket.TR_FORCE_EARLY_RETURN,
164: byteOutStream);
165: switch (reply.errorCode()) {
166: case JdwpReplyPacket.INVALID_THREAD:
167: throw new ObjectCollectedException(
168: JDIMessages.ThreadReferenceImpl_thread_object_invalid);
169: case JdwpReplyPacket.INVALID_OBJECT:
170: throw new ClassNotLoadedException(
171: JDIMessages.ThreadReferenceImpl_thread_or_value_unknown);
172: case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
173: case JdwpReplyPacket.THREAD_NOT_ALIVE:
174: throw new IncompatibleThreadStateException(
175: JDIMessages.ThreadReferenceImpl_thread_not_suspended);
176: case JdwpReplyPacket.NOT_IMPLEMENTED:
177: throw new UnsupportedOperationException(
178: JDIMessages.ThreadReferenceImpl_no_force_early_return_on_threads);
179: case JdwpReplyPacket.OPAQUE_FRAME:
180: throw new NativeMethodException(
181: JDIMessages.ThreadReferenceImpl_thread_cannot_force_native_method);
182: case JdwpReplyPacket.NO_MORE_FRAMES:
183: throw new InvalidStackFrameException(
184: JDIMessages.ThreadReferenceImpl_thread_no_stackframes);
185: case JdwpReplyPacket.TYPE_MISMATCH:
186: throw new InvalidTypeException(
187: JDIMessages.ThreadReferenceImpl_incapatible_return_type);
188: case JdwpReplyPacket.VM_DEAD:
189: throw new VMDisconnectedException(JDIMessages.vm_dead);
190: }
191: defaultReplyErrorHandler(reply.errorCode());
192: } catch (IOException e) {
193: defaultIOExceptionHandler(e);
194: } finally {
195: handledJdwpRequest();
196: }
197: }
198:
199: /**
200: * @returns Returns the StackFrame at the given index in the thread's current call stack.
201: */
202: public StackFrame frame(int index)
203: throws IncompatibleThreadStateException {
204: return (StackFrameImpl) frames(index, 1).get(0);
205: }
206:
207: /**
208: * @see com.sun.jdi.ThreadReference#frameCount()
209: */
210: public int frameCount() throws IncompatibleThreadStateException {
211: // Note that this information should not be cached.
212: initJdwpRequest();
213: try {
214: JdwpReplyPacket replyPacket = requestVM(
215: JdwpCommandPacket.TR_FRAME_COUNT, this );
216: switch (replyPacket.errorCode()) {
217: case JdwpReplyPacket.INVALID_THREAD:
218: throw new ObjectCollectedException();
219: case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
220: throw new IncompatibleThreadStateException(
221: JDIMessages.ThreadReferenceImpl_Thread_was_not_suspended_1);
222: }
223: defaultReplyErrorHandler(replyPacket.errorCode());
224:
225: DataInputStream replyData = replyPacket.dataInStream();
226: int result = readInt("frame count", replyData); //$NON-NLS-1$
227: return result;
228: } catch (IOException e) {
229: defaultIOExceptionHandler(e);
230: return 0;
231: } finally {
232: handledJdwpRequest();
233: }
234: }
235:
236: /**
237: * @returns Returns a List containing each StackFrame in the thread's current call stack.
238: */
239: public List frames() throws IncompatibleThreadStateException {
240: return frames(0, -1);
241: }
242:
243: /**
244: * @returns Returns a List containing each StackFrame in the thread's current call stack.
245: */
246: public List frames(int start, int length)
247: throws IndexOutOfBoundsException,
248: IncompatibleThreadStateException {
249: // Note that this information should not be cached.
250: initJdwpRequest();
251: try {
252: ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
253: DataOutputStream outData = new DataOutputStream(outBytes);
254: write(this , outData);
255: writeInt(start, "start", outData); //$NON-NLS-1$
256: writeInt(length, "length", outData); //$NON-NLS-1$
257:
258: JdwpReplyPacket replyPacket = requestVM(
259: JdwpCommandPacket.TR_FRAMES, outBytes);
260: switch (replyPacket.errorCode()) {
261: case JdwpReplyPacket.INVALID_THREAD:
262: throw new ObjectCollectedException();
263: case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
264: throw new IncompatibleThreadStateException(
265: JDIMessages.ThreadReferenceImpl_Thread_was_not_suspended_1);
266: case JdwpReplyPacket.INVALID_INDEX:
267: throw new IndexOutOfBoundsException(
268: JDIMessages.ThreadReferenceImpl_Invalid_index_of_stack_frames_given_4);
269: }
270: defaultReplyErrorHandler(replyPacket.errorCode());
271:
272: DataInputStream replyData = replyPacket.dataInStream();
273: int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
274: List frames = new ArrayList(nrOfElements);
275: for (int i = 0; i < nrOfElements; i++) {
276: StackFrameImpl frame = StackFrameImpl.readWithLocation(
277: this , this , replyData);
278: if (frame == null) {
279: continue;
280: }
281: frames.add(frame);
282: }
283: return frames;
284: } catch (IOException e) {
285: defaultIOExceptionHandler(e);
286: return null;
287: } finally {
288: handledJdwpRequest();
289: }
290: }
291:
292: /**
293: * Interrupts this thread
294: * @see com.sun.jdi.ThreadReference#interrupt()
295: */
296: public void interrupt() {
297: // Note that this information should not be cached.
298: initJdwpRequest();
299: try {
300: requestVM(JdwpCommandPacket.TR_INTERRUPT, this );
301: } finally {
302: handledJdwpRequest();
303: }
304: }
305:
306: /**
307: * @return Returns whether the thread is suspended at a breakpoint.
308: */
309: public boolean isAtBreakpoint() {
310: return isSuspended() && fIsAtBreakpoint;
311: }
312:
313: /**
314: * @return Returns whether the thread has been suspended by the the debugger.
315: */
316: public boolean isSuspended() {
317: // Note that this information should not be cached.
318: initJdwpRequest();
319: try {
320: JdwpReplyPacket replyPacket = requestVM(
321: JdwpCommandPacket.TR_STATUS, this );
322: switch (replyPacket.errorCode()) {
323: case JdwpReplyPacket.INVALID_THREAD:
324: throw new ObjectCollectedException();
325: }
326: defaultReplyErrorHandler(replyPacket.errorCode());
327: DataInputStream replyData = replyPacket.dataInStream();
328: //remove the thread status reply
329: readInt("thread status", threadStatusMap(), replyData); //$NON-NLS-1$
330: int suspendStatus = readInt(
331: "suspend status", suspendStatusStrings(), replyData); //$NON-NLS-1$
332: boolean result = suspendStatus == SUSPEND_STATUS_SUSPENDED;
333: return result;
334: } catch (IOException e) {
335: defaultIOExceptionHandler(e);
336: return false;
337: } finally {
338: handledJdwpRequest();
339: }
340: }
341:
342: /**
343: * @return Returns the name of this thread.
344: */
345: public String name() {
346: initJdwpRequest();
347: try {
348: JdwpReplyPacket replyPacket = requestVM(
349: JdwpCommandPacket.TR_NAME, this );
350: switch (replyPacket.errorCode()) {
351: case JdwpReplyPacket.INVALID_THREAD:
352: throw new ObjectCollectedException();
353: }
354: defaultReplyErrorHandler(replyPacket.errorCode());
355: DataInputStream replyData = replyPacket.dataInStream();
356: return readString("name", replyData); //$NON-NLS-1$
357: } catch (IOException e) {
358: defaultIOExceptionHandler(e);
359: return null;
360: } finally {
361: handledJdwpRequest();
362: }
363: }
364:
365: /**
366: * @return Returns a List containing an ObjectReference for each monitor owned by the thread.
367: */
368: public List ownedMonitors() throws IncompatibleThreadStateException {
369: if (!virtualMachine().canGetOwnedMonitorInfo()) {
370: throw new UnsupportedOperationException();
371: }
372: // Note that this information should not be cached.
373: initJdwpRequest();
374: try {
375: JdwpReplyPacket replyPacket = requestVM(
376: JdwpCommandPacket.TR_OWNED_MONITORS, this );
377: switch (replyPacket.errorCode()) {
378: case JdwpReplyPacket.INVALID_THREAD:
379: throw new ObjectCollectedException();
380: case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
381: throw new IncompatibleThreadStateException(
382: JDIMessages.ThreadReferenceImpl_Thread_was_not_suspended_5);
383: }
384: defaultReplyErrorHandler(replyPacket.errorCode());
385: DataInputStream replyData = replyPacket.dataInStream();
386:
387: int nrOfMonitors = readInt("nr of monitors", replyData); //$NON-NLS-1$
388: List result = new ArrayList(nrOfMonitors);
389: for (int i = 0; i < nrOfMonitors; i++) {
390: result.add(ObjectReferenceImpl.readObjectRefWithTag(
391: this , replyData));
392: }
393: return result;
394: } catch (IOException e) {
395: defaultIOExceptionHandler(e);
396: return null;
397: } finally {
398: handledJdwpRequest();
399: }
400: }
401:
402: /**
403: * @see com.sun.jdi.ThreadReference#ownedMonitorsAndFrames()
404: * @since 3.3
405: */
406: public List ownedMonitorsAndFrames()
407: throws IncompatibleThreadStateException {
408: initJdwpRequest();
409: try {
410: JdwpReplyPacket replyPacket = requestVM(
411: JdwpCommandPacket.TR_OWNED_MONITOR_STACK_DEPTH,
412: this );
413: switch (replyPacket.errorCode()) {
414: case JdwpReplyPacket.INVALID_THREAD:
415: case JdwpReplyPacket.INVALID_OBJECT:
416: throw new ObjectCollectedException(
417: JDIMessages.ThreadReferenceImpl_thread_object_invalid);
418: case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
419: throw new IncompatibleThreadStateException(
420: JDIMessages.ThreadReferenceImpl_Thread_was_not_suspended_5);
421: case JdwpReplyPacket.NOT_IMPLEMENTED:
422: throw new UnsupportedOperationException(
423: JDIMessages.ThreadReferenceImpl_no_force_early_return_on_threads);
424: case JdwpReplyPacket.VM_DEAD:
425: throw new VMDisconnectedException(JDIMessages.vm_dead);
426: }
427: defaultReplyErrorHandler(replyPacket.errorCode());
428: DataInputStream replyData = replyPacket.dataInStream();
429:
430: int owned = readInt("owned monitors", replyData); //$NON-NLS-1$
431: List result = new ArrayList(owned);
432: for (int i = 0; i < owned; i++) {
433: result.add(new MonitorInfoImpl(this , readInt(
434: "stack depth", replyData), //$NON-NLS-1$
435: ObjectReferenceImpl.readObjectRefWithTag(this ,
436: replyData), virtualMachineImpl()));
437: }
438: return result;
439: } catch (IOException e) {
440: defaultIOExceptionHandler(e);
441: return null;
442: } finally {
443: handledJdwpRequest();
444: }
445: }
446:
447: /**
448: * Resumes this thread.
449: * @see com.sun.jdi.ThreadReference#resume()
450: */
451: public void resume() {
452: initJdwpRequest();
453: try {
454: JdwpReplyPacket replyPacket = requestVM(
455: JdwpCommandPacket.TR_RESUME, this );
456: switch (replyPacket.errorCode()) {
457: case JdwpReplyPacket.INVALID_THREAD:
458: throw new ObjectCollectedException();
459: }
460: defaultReplyErrorHandler(replyPacket.errorCode());
461: resetEventFlags();
462: } finally {
463: handledJdwpRequest();
464: }
465: }
466:
467: /**
468: * @return Returns the thread's status.
469: */
470: public int status() {
471: // Note that this information should not be cached.
472: initJdwpRequest();
473: try {
474: JdwpReplyPacket replyPacket = requestVM(
475: JdwpCommandPacket.TR_STATUS, this );
476: switch (replyPacket.errorCode()) {
477: case JdwpReplyPacket.ABSENT_INFORMATION:
478: return THREAD_STATUS_UNKNOWN;
479: case JdwpReplyPacket.INVALID_THREAD:
480: return THREAD_STATUS_NOT_STARTED;
481: }
482: defaultReplyErrorHandler(replyPacket.errorCode());
483: DataInputStream replyData = replyPacket.dataInStream();
484: int threadStatus = readInt(
485: "thread status", threadStatusMap(), replyData); //$NON-NLS-1$
486: readInt("suspend status", suspendStatusStrings(), replyData); //$NON-NLS-1$
487: switch (threadStatus) {
488: case JDWP_THREAD_STATUS_ZOMBIE:
489: return THREAD_STATUS_ZOMBIE;
490: case JDWP_THREAD_STATUS_RUNNING:
491: return THREAD_STATUS_RUNNING;
492: case JDWP_THREAD_STATUS_SLEEPING:
493: return THREAD_STATUS_SLEEPING;
494: case JDWP_THREAD_STATUS_MONITOR:
495: return THREAD_STATUS_MONITOR;
496: case JDWP_THREAD_STATUS_WAIT:
497: return THREAD_STATUS_WAIT;
498: case -1: // see bug 30816
499: return THREAD_STATUS_UNKNOWN;
500: }
501: throw new InternalException(
502: JDIMessages.ThreadReferenceImpl_Unknown_thread_status_received___6
503: + threadStatus);
504: } catch (IOException e) {
505: defaultIOExceptionHandler(e);
506: return 0;
507: } finally {
508: handledJdwpRequest();
509: }
510: }
511:
512: /**
513: * Stops this thread with an asynchronous exception.
514: * @see com.sun.jdi.ThreadReference#stop(com.sun.jdi.ObjectReference)
515: */
516: public void stop(ObjectReference throwable)
517: throws InvalidTypeException {
518: checkVM(throwable);
519: ObjectReferenceImpl throwableImpl = (ObjectReferenceImpl) throwable;
520:
521: initJdwpRequest();
522: try {
523: ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
524: DataOutputStream outData = new DataOutputStream(outBytes);
525: write(this , outData);
526: throwableImpl.write(this , outData);
527:
528: JdwpReplyPacket replyPacket = requestVM(
529: JdwpCommandPacket.TR_STOP, outBytes);
530: switch (replyPacket.errorCode()) {
531: case JdwpReplyPacket.INVALID_THREAD:
532: throw new ObjectCollectedException();
533: case JdwpReplyPacket.INVALID_CLASS:
534: throw new InvalidTypeException(
535: JDIMessages.ThreadReferenceImpl_Stop_argument_not_an_instance_of_java_lang_Throwable_in_the_target_VM_7);
536: }
537: defaultReplyErrorHandler(replyPacket.errorCode());
538: } catch (IOException e) {
539: defaultIOExceptionHandler(e);
540: } finally {
541: handledJdwpRequest();
542: }
543: }
544:
545: /**
546: * Suspends this thread.
547: * @see com.sun.jdi.ThreadReference#suspend()
548: */
549: public void suspend() {
550: initJdwpRequest();
551: try {
552: JdwpReplyPacket replyPacket = requestVM(
553: JdwpCommandPacket.TR_SUSPEND, this );
554: switch (replyPacket.errorCode()) {
555: case JdwpReplyPacket.INVALID_THREAD:
556: throw new ObjectCollectedException();
557: }
558: defaultReplyErrorHandler(replyPacket.errorCode());
559: } finally {
560: handledJdwpRequest();
561: }
562: }
563:
564: /**
565: * @return Returns the number of pending suspends for this thread.
566: */
567: public int suspendCount() {
568: // Note that this information should not be cached.
569: initJdwpRequest();
570: try {
571: JdwpReplyPacket replyPacket = requestVM(
572: JdwpCommandPacket.TR_SUSPEND_COUNT, this );
573: defaultReplyErrorHandler(replyPacket.errorCode());
574: DataInputStream replyData = replyPacket.dataInStream();
575: int result = readInt("suspend count", replyData); //$NON-NLS-1$
576: return result;
577: } catch (IOException e) {
578: defaultIOExceptionHandler(e);
579: return 0;
580: } finally {
581: handledJdwpRequest();
582: }
583: }
584:
585: /**
586: * @return Returns this thread's thread group.
587: */
588: public ThreadGroupReference threadGroup() {
589: if (fThreadGroup != null) {
590: return fThreadGroup;
591: }
592: initJdwpRequest();
593: try {
594: JdwpReplyPacket replyPacket = requestVM(
595: JdwpCommandPacket.TR_THREAD_GROUP, this );
596: switch (replyPacket.errorCode()) {
597: case JdwpReplyPacket.INVALID_THREAD:
598: throw new ObjectCollectedException();
599: }
600: defaultReplyErrorHandler(replyPacket.errorCode());
601: DataInputStream replyData = replyPacket.dataInStream();
602: fThreadGroup = ThreadGroupReferenceImpl.read(this ,
603: replyData);
604: return fThreadGroup;
605: } catch (IOException e) {
606: defaultIOExceptionHandler(e);
607: return null;
608: } finally {
609: handledJdwpRequest();
610: }
611: }
612:
613: /**
614: * Simulate the execution of a return instruction instead of executing the next bytecode in a method.
615: * @return Returns whether any finally or synchronized blocks are enclosing the current instruction.
616: */
617: public boolean doReturn(Value returnValue,
618: boolean triggerFinallyAndSynchronized)
619: throws org.eclipse.jdi.hcr.OperationRefusedException {
620: virtualMachineImpl().checkHCRSupported();
621: ValueImpl valueImpl;
622: if (returnValue != null) { // null is used if no value is returned.
623: checkVM(returnValue);
624: valueImpl = (ValueImpl) returnValue;
625: } else {
626: try {
627: TypeImpl returnType = (TypeImpl) frame(0).location()
628: .method().returnType();
629: valueImpl = (ValueImpl) returnType.createNullValue();
630: } catch (IncompatibleThreadStateException e) {
631: throw new org.eclipse.jdi.hcr.OperationRefusedException(
632: e.toString());
633: } catch (ClassNotLoadedException e) {
634: throw new org.eclipse.jdi.hcr.OperationRefusedException(
635: e.toString());
636: }
637: }
638:
639: // Note that this information should not be cached.
640: initJdwpRequest();
641: try {
642: ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
643: DataOutputStream outData = new DataOutputStream(outBytes);
644: write(this , outData);
645: valueImpl.writeWithTag(this , outData);
646: writeBoolean(triggerFinallyAndSynchronized,
647: "trigger finaly+sync", outData); //$NON-NLS-1$
648:
649: JdwpReplyPacket replyPacket = requestVM(
650: JdwpCommandPacket.HCR_DO_RETURN, outBytes);
651: switch (replyPacket.errorCode()) {
652: case JdwpReplyPacket.INVALID_THREAD:
653: throw new ObjectCollectedException();
654: }
655: defaultReplyErrorHandler(replyPacket.errorCode());
656:
657: DataInputStream replyData = replyPacket.dataInStream();
658: boolean result = readBoolean("is enclosed", replyData); //$NON-NLS-1$
659: return result;
660: } catch (IOException e) {
661: defaultIOExceptionHandler(e);
662: return false;
663: } finally {
664: handledJdwpRequest();
665: }
666: }
667:
668: /**
669: * @return Returns description of Mirror object.
670: */
671: public String toString() {
672: try {
673: return MessageFormat.format(
674: JDIMessages.ThreadReferenceImpl_8, new String[] {
675: type().toString(), name(),
676: getObjectID().toString() });
677: } catch (ObjectCollectedException e) {
678: return JDIMessages.ThreadReferenceImpl__Garbage_Collected__ThreadReference__9
679: + idString();
680: } catch (Exception e) {
681: return fDescription;
682: }
683: }
684:
685: /**
686: * @return Reads JDWP representation and returns new instance.
687: */
688: public static ThreadReferenceImpl read(MirrorImpl target,
689: DataInputStream in) throws IOException {
690: VirtualMachineImpl vmImpl = target.virtualMachineImpl();
691: JdwpThreadID ID = new JdwpThreadID(vmImpl);
692: ID.read(in);
693: if (target.fVerboseWriter != null)
694: target.fVerboseWriter
695: .println("threadReference", ID.value()); //$NON-NLS-1$
696:
697: if (ID.isNull())
698: return null;
699:
700: ThreadReferenceImpl mirror = (ThreadReferenceImpl) vmImpl
701: .getCachedMirror(ID);
702: if (mirror == null) {
703: mirror = new ThreadReferenceImpl(vmImpl, ID);
704: vmImpl.addCachedMirror(mirror);
705: }
706: return mirror;
707: }
708:
709: /**
710: * Retrieves constant mappings.
711: */
712: public static void getConstantMaps() {
713: if (fgThreadStatusMap != null) {
714: return;
715: }
716:
717: Field[] fields = ThreadReferenceImpl.class.getDeclaredFields();
718: fgThreadStatusMap = new HashMap();
719: fgSuspendStatusStrings = new String[32]; // Int
720:
721: for (int i = 0; i < fields.length; i++) {
722: Field field = fields[i];
723: if ((field.getModifiers() & Modifier.PUBLIC) == 0
724: || (field.getModifiers() & Modifier.STATIC) == 0
725: || (field.getModifiers() & Modifier.FINAL) == 0)
726: continue;
727:
728: try {
729: String name = field.getName();
730: int value = field.getInt(null);
731: Integer intValue = new Integer(value);
732:
733: if (name.startsWith("JDWP_THREAD_STATUS_")) { //$NON-NLS-1$
734: name = name.substring(19);
735: fgThreadStatusMap.put(intValue, name);
736: } else if (name.startsWith("SUSPEND_STATUS_")) { //$NON-NLS-1$
737: name = name.substring(15);
738: for (int j = 0; j < fgSuspendStatusStrings.length; j++) {
739: if ((1 << j & value) != 0) {
740: fgSuspendStatusStrings[j] = name;
741: break;
742: }
743: }
744: }
745: } catch (IllegalAccessException e) {
746: // Will not occur for own class.
747: } catch (IllegalArgumentException e) {
748: // Should not occur.
749: // We should take care that all public static final constants
750: // in this class are numbers that are convertible to int.
751: }
752: }
753: }
754:
755: /**
756: * @return Returns a map with string representations of tags.
757: */
758: public static Map threadStatusMap() {
759: getConstantMaps();
760: return fgThreadStatusMap;
761: }
762:
763: /**
764: * @return Returns a map with string representations of tags.
765: */
766: public static String[] suspendStatusStrings() {
767: getConstantMaps();
768: return fgSuspendStatusStrings;
769: }
770:
771: /**
772: * @see ThreadReference#popFrames(StackFrame)
773: */
774: public void popFrames(StackFrame frameToPop)
775: throws IncompatibleThreadStateException {
776: if (!isSuspended()) {
777: throw new IncompatibleThreadStateException();
778: }
779: if (!virtualMachineImpl().canPopFrames()) {
780: throw new UnsupportedOperationException();
781: }
782:
783: StackFrameImpl frame = (StackFrameImpl) frameToPop;
784:
785: initJdwpRequest();
786: try {
787: ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
788: DataOutputStream outData = new DataOutputStream(outBytes);
789: frame.writeWithThread(frame, outData);
790:
791: JdwpReplyPacket replyPacket = requestVM(
792: JdwpCommandPacket.SF_POP_FRAME, outBytes);
793: switch (replyPacket.errorCode()) {
794: case JdwpReplyPacket.INVALID_THREAD:
795: throw new InvalidStackFrameException();
796: case JdwpReplyPacket.INVALID_FRAMEID:
797: throw new InvalidStackFrameException(
798: JDIMessages.ThreadReferenceImpl_Unable_to_pop_the_requested_stack_frame_from_the_call_stack__Reasons_include__The_frame_id_was_invalid__The_thread_was_resumed__10);
799: case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
800: throw new IncompatibleThreadStateException(
801: JDIMessages.ThreadReferenceImpl_Unable_to_pop_the_requested_stack_frame__The_requested_stack_frame_is_not_suspended_11);
802: case JdwpReplyPacket.NO_MORE_FRAMES:
803: throw new InvalidStackFrameException(
804: JDIMessages.ThreadReferenceImpl_Unable_to_pop_the_requested_stack_frame_from_the_call_stack__Reasons_include__The_requested_frame_was_the_last_frame_on_the_call_stack__The_requested_frame_was_the_last_frame_above_a_native_frame__12);
805: default:
806: defaultReplyErrorHandler(replyPacket.errorCode());
807: }
808: } catch (IOException ioe) {
809: defaultIOExceptionHandler(ioe);
810: } finally {
811: handledJdwpRequest();
812: }
813: }
814:
815: }
|