1 /* 2 * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.jdi; 27 28 import com.sun.jdi.*; 29 import com.sun.jdi.request.*; 30 import com.sun.tools.jdi.JDWP; 31 32 import java.util.*; 33 34 /** 35 * This interface is used to create and remove Breakpoints, Watchpoints, 36 * etc. 37 * It include implementations of all the request interfaces.. 38 */ 39 // Warnings from List filters and List[] requestLists is hard to fix. 40 // Remove SuppressWarning when we fix the warnings from List filters 41 // and List[] requestLists. The generic array is not supported. 42 @SuppressWarnings("unchecked") 43 class EventRequestManagerImpl extends MirrorImpl 44 implements EventRequestManager 45 { 46 List<? extends EventRequest>[] requestLists; 47 private static int methodExitEventCmd = 0; 48 JDWPtoJDISuspendPolicy(byte jdwpPolicy)49 static int JDWPtoJDISuspendPolicy(byte jdwpPolicy) { 50 switch(jdwpPolicy) { 51 case JDWP.SuspendPolicy.ALL: 52 return EventRequest.SUSPEND_ALL; 53 case JDWP.SuspendPolicy.EVENT_THREAD: 54 return EventRequest.SUSPEND_EVENT_THREAD; 55 case JDWP.SuspendPolicy.NONE: 56 return EventRequest.SUSPEND_NONE; 57 default: 58 throw new IllegalArgumentException("Illegal policy constant: " + jdwpPolicy); 59 } 60 } 61 JDItoJDWPSuspendPolicy(int jdiPolicy)62 static byte JDItoJDWPSuspendPolicy(int jdiPolicy) { 63 switch(jdiPolicy) { 64 case EventRequest.SUSPEND_ALL: 65 return JDWP.SuspendPolicy.ALL; 66 case EventRequest.SUSPEND_EVENT_THREAD: 67 return JDWP.SuspendPolicy.EVENT_THREAD; 68 case EventRequest.SUSPEND_NONE: 69 return JDWP.SuspendPolicy.NONE; 70 default: 71 throw new IllegalArgumentException("Illegal policy constant: " + jdiPolicy); 72 } 73 } 74 75 /* 76 * Override superclass back to default equality 77 */ equals(Object obj)78 public boolean equals(Object obj) { 79 return this == obj; 80 } 81 hashCode()82 public int hashCode() { 83 return System.identityHashCode(this); 84 } 85 86 abstract class EventRequestImpl extends MirrorImpl implements EventRequest { 87 int id; 88 89 /* 90 * This list is not protected by a synchronized wrapper. All 91 * access/modification should be protected by synchronizing on 92 * the enclosing instance of EventRequestImpl. 93 */ 94 List<Object> filters = new ArrayList<>(); 95 96 boolean isEnabled = false; 97 boolean deleted = false; 98 byte suspendPolicy = JDWP.SuspendPolicy.ALL; 99 private Map<Object, Object> clientProperties = null; 100 EventRequestImpl()101 EventRequestImpl() { 102 super(EventRequestManagerImpl.this.vm); 103 } 104 105 106 /* 107 * Override superclass back to default equality 108 */ equals(Object obj)109 public boolean equals(Object obj) { 110 return this == obj; 111 } 112 hashCode()113 public int hashCode() { 114 return System.identityHashCode(this); 115 } 116 eventCmd()117 abstract int eventCmd(); 118 invalidState()119 InvalidRequestStateException invalidState() { 120 return new InvalidRequestStateException(toString()); 121 } 122 state()123 String state() { 124 return deleted? " (deleted)" : 125 (isEnabled()? " (enabled)" : " (disabled)"); 126 } 127 128 /** 129 * @return all the event request of this kind 130 */ requestList()131 List requestList() { 132 return EventRequestManagerImpl.this.requestList(eventCmd()); 133 } 134 135 /** 136 * delete the event request 137 */ delete()138 void delete() { 139 if (!deleted) { 140 requestList().remove(this); 141 disable(); /* must do BEFORE delete */ 142 deleted = true; 143 } 144 } 145 isEnabled()146 public boolean isEnabled() { 147 return isEnabled; 148 } 149 enable()150 public void enable() { 151 setEnabled(true); 152 } 153 disable()154 public void disable() { 155 setEnabled(false); 156 } 157 setEnabled(boolean val)158 public synchronized void setEnabled(boolean val) { 159 if (deleted) { 160 throw invalidState(); 161 } else { 162 if (val != isEnabled) { 163 if (isEnabled) { 164 clear(); 165 } else { 166 set(); 167 } 168 } 169 } 170 } 171 addCountFilter(int count)172 public synchronized void addCountFilter(int count) { 173 if (isEnabled() || deleted) { 174 throw invalidState(); 175 } 176 if (count < 1) { 177 throw new IllegalArgumentException("count is less than one"); 178 } 179 filters.add(JDWP.EventRequest.Set.Modifier.Count.create(count)); 180 } 181 setSuspendPolicy(int policy)182 public void setSuspendPolicy(int policy) { 183 if (isEnabled() || deleted) { 184 throw invalidState(); 185 } 186 suspendPolicy = JDItoJDWPSuspendPolicy(policy); 187 } 188 suspendPolicy()189 public int suspendPolicy() { 190 return JDWPtoJDISuspendPolicy(suspendPolicy); 191 } 192 193 /** 194 * set (enable) the event request 195 */ set()196 synchronized void set() { 197 JDWP.EventRequest.Set.Modifier[] mods = 198 filters.toArray( 199 new JDWP.EventRequest.Set.Modifier[filters.size()]); 200 try { 201 id = JDWP.EventRequest.Set.process(vm, (byte)eventCmd(), 202 suspendPolicy, mods).requestID; 203 } catch (JDWPException exc) { 204 throw exc.toJDIException(); 205 } 206 isEnabled = true; 207 } 208 clear()209 synchronized void clear() { 210 try { 211 JDWP.EventRequest.Clear.process(vm, (byte)eventCmd(), id); 212 } catch (JDWPException exc) { 213 throw exc.toJDIException(); 214 } 215 isEnabled = false; 216 } 217 218 /** 219 * @return a small Map 220 * @see #putProperty 221 * @see #getProperty 222 */ getProperties()223 private Map<Object, Object> getProperties() { 224 if (clientProperties == null) { 225 clientProperties = new HashMap<Object, Object>(2); 226 } 227 return clientProperties; 228 } 229 230 /** 231 * Returns the value of the property with the specified key. Only 232 * properties added with <code>putProperty</code> will return 233 * a non-null value. 234 * 235 * @return the value of this property or null 236 * @see #putProperty 237 */ getProperty(Object key)238 public final Object getProperty(Object key) { 239 if (clientProperties == null) { 240 return null; 241 } else { 242 return getProperties().get(key); 243 } 244 } 245 246 /** 247 * Add an arbitrary key/value "property" to this component. 248 * 249 * @see #getProperty 250 */ putProperty(Object key, Object value)251 public final void putProperty(Object key, Object value) { 252 if (value != null) { 253 getProperties().put(key, value); 254 } else { 255 getProperties().remove(key); 256 } 257 } 258 } 259 260 abstract class ThreadVisibleEventRequestImpl extends EventRequestImpl { addThreadFilter(ThreadReference thread)261 public synchronized void addThreadFilter(ThreadReference thread) { 262 validateMirror(thread); 263 if (isEnabled() || deleted) { 264 throw invalidState(); 265 } 266 filters.add(JDWP.EventRequest.Set.Modifier.ThreadOnly 267 .create((ThreadReferenceImpl)thread)); 268 } 269 } 270 271 abstract class ClassVisibleEventRequestImpl 272 extends ThreadVisibleEventRequestImpl { addClassFilter(ReferenceType clazz)273 public synchronized void addClassFilter(ReferenceType clazz) { 274 validateMirror(clazz); 275 if (isEnabled() || deleted) { 276 throw invalidState(); 277 } 278 filters.add(JDWP.EventRequest.Set.Modifier.ClassOnly 279 .create((ReferenceTypeImpl)clazz)); 280 } 281 addClassFilter(String classPattern)282 public synchronized void addClassFilter(String classPattern) { 283 if (isEnabled() || deleted) { 284 throw invalidState(); 285 } 286 if (classPattern == null) { 287 throw new NullPointerException(); 288 } 289 filters.add(JDWP.EventRequest.Set.Modifier.ClassMatch 290 .create(classPattern)); 291 } 292 addClassExclusionFilter(String classPattern)293 public synchronized void addClassExclusionFilter(String classPattern) { 294 if (isEnabled() || deleted) { 295 throw invalidState(); 296 } 297 if (classPattern == null) { 298 throw new NullPointerException(); 299 } 300 filters.add(JDWP.EventRequest.Set.Modifier.ClassExclude 301 .create(classPattern)); 302 } 303 addInstanceFilter(ObjectReference instance)304 public synchronized void addInstanceFilter(ObjectReference instance) { 305 validateMirror(instance); 306 if (isEnabled() || deleted) { 307 throw invalidState(); 308 } 309 if (!vm.canUseInstanceFilters()) { 310 throw new UnsupportedOperationException( 311 "target does not support instance filters"); 312 } 313 filters.add(JDWP.EventRequest.Set.Modifier.InstanceOnly 314 .create((ObjectReferenceImpl)instance)); 315 } 316 } 317 318 class BreakpointRequestImpl extends ClassVisibleEventRequestImpl 319 implements BreakpointRequest { 320 private final Location location; 321 BreakpointRequestImpl(Location location)322 BreakpointRequestImpl(Location location) { 323 this.location = location; 324 filters.add(0,JDWP.EventRequest.Set.Modifier.LocationOnly 325 .create(location)); 326 requestList().add(this); 327 } 328 location()329 public Location location() { 330 return location; 331 } 332 eventCmd()333 int eventCmd() { 334 return JDWP.EventKind.BREAKPOINT; 335 } 336 toString()337 public String toString() { 338 return "breakpoint request " + location() + state(); 339 } 340 } 341 342 class ClassPrepareRequestImpl extends ClassVisibleEventRequestImpl 343 implements ClassPrepareRequest { ClassPrepareRequestImpl()344 ClassPrepareRequestImpl() { 345 requestList().add(this); 346 } 347 eventCmd()348 int eventCmd() { 349 return JDWP.EventKind.CLASS_PREPARE; 350 } 351 addSourceNameFilter(String sourceNamePattern)352 public synchronized void addSourceNameFilter(String sourceNamePattern) { 353 if (isEnabled() || deleted) { 354 throw invalidState(); 355 } 356 if (!vm.canUseSourceNameFilters()) { 357 throw new UnsupportedOperationException( 358 "target does not support source name filters"); 359 } 360 if (sourceNamePattern == null) { 361 throw new NullPointerException(); 362 } 363 364 filters.add(JDWP.EventRequest.Set.Modifier.SourceNameMatch 365 .create(sourceNamePattern)); 366 } 367 toString()368 public String toString() { 369 return "class prepare request " + state(); 370 } 371 } 372 373 class ClassUnloadRequestImpl extends ClassVisibleEventRequestImpl 374 implements ClassUnloadRequest { ClassUnloadRequestImpl()375 ClassUnloadRequestImpl() { 376 requestList().add(this); 377 } 378 eventCmd()379 int eventCmd() { 380 return JDWP.EventKind.CLASS_UNLOAD; 381 } 382 toString()383 public String toString() { 384 return "class unload request " + state(); 385 } 386 } 387 388 class ExceptionRequestImpl extends ClassVisibleEventRequestImpl 389 implements ExceptionRequest { 390 ReferenceType exception = null; 391 boolean caught = true; 392 boolean uncaught = true; 393 ExceptionRequestImpl(ReferenceType refType, boolean notifyCaught, boolean notifyUncaught)394 ExceptionRequestImpl(ReferenceType refType, 395 boolean notifyCaught, boolean notifyUncaught) { 396 exception = refType; 397 caught = notifyCaught; 398 uncaught = notifyUncaught; 399 { 400 ReferenceTypeImpl exc; 401 if (exception == null) { 402 exc = new ClassTypeImpl(vm, 0); 403 } else { 404 exc = (ReferenceTypeImpl)exception; 405 } 406 filters.add(JDWP.EventRequest.Set.Modifier.ExceptionOnly. 407 create(exc, caught, uncaught)); 408 } 409 requestList().add(this); 410 } 411 exception()412 public ReferenceType exception() { 413 return exception; 414 } 415 notifyCaught()416 public boolean notifyCaught() { 417 return caught; 418 } 419 notifyUncaught()420 public boolean notifyUncaught() { 421 return uncaught; 422 } 423 eventCmd()424 int eventCmd() { 425 return JDWP.EventKind.EXCEPTION; 426 } 427 toString()428 public String toString() { 429 return "exception request " + exception() + state(); 430 } 431 } 432 433 class MethodEntryRequestImpl extends ClassVisibleEventRequestImpl 434 implements MethodEntryRequest { MethodEntryRequestImpl()435 MethodEntryRequestImpl() { 436 requestList().add(this); 437 } 438 eventCmd()439 int eventCmd() { 440 return JDWP.EventKind.METHOD_ENTRY; 441 } 442 toString()443 public String toString() { 444 return "method entry request " + state(); 445 } 446 } 447 448 class MethodExitRequestImpl extends ClassVisibleEventRequestImpl 449 implements MethodExitRequest { MethodExitRequestImpl()450 MethodExitRequestImpl() { 451 if (methodExitEventCmd == 0) { 452 /* 453 * If we can get return values, then we always get them. 454 * Thus, for JDI MethodExitRequests, we always use the 455 * same JDWP EventKind. Here we decide which to use and 456 * save it so that it will be used for all future 457 * MethodExitRequests. 458 * 459 * This call to canGetMethodReturnValues can't 460 * be done in the EventRequestManager ctor because that is too early. 461 */ 462 if (vm.canGetMethodReturnValues()) { 463 methodExitEventCmd = JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE; 464 } else { 465 methodExitEventCmd = JDWP.EventKind.METHOD_EXIT; 466 } 467 } 468 requestList().add(this); 469 } 470 eventCmd()471 int eventCmd() { 472 return EventRequestManagerImpl.methodExitEventCmd; 473 } 474 toString()475 public String toString() { 476 return "method exit request " + state(); 477 } 478 } 479 480 class MonitorContendedEnterRequestImpl extends ClassVisibleEventRequestImpl 481 implements MonitorContendedEnterRequest { MonitorContendedEnterRequestImpl()482 MonitorContendedEnterRequestImpl() { 483 requestList().add(this); 484 } 485 eventCmd()486 int eventCmd() { 487 return JDWP.EventKind.MONITOR_CONTENDED_ENTER; 488 } 489 toString()490 public String toString() { 491 return "monitor contended enter request " + state(); 492 } 493 } 494 495 class MonitorContendedEnteredRequestImpl extends ClassVisibleEventRequestImpl 496 implements MonitorContendedEnteredRequest { MonitorContendedEnteredRequestImpl()497 MonitorContendedEnteredRequestImpl() { 498 requestList().add(this); 499 } 500 eventCmd()501 int eventCmd() { 502 return JDWP.EventKind.MONITOR_CONTENDED_ENTERED; 503 } 504 toString()505 public String toString() { 506 return "monitor contended entered request " + state(); 507 } 508 } 509 510 class MonitorWaitRequestImpl extends ClassVisibleEventRequestImpl 511 implements MonitorWaitRequest { MonitorWaitRequestImpl()512 MonitorWaitRequestImpl() { 513 requestList().add(this); 514 } 515 eventCmd()516 int eventCmd() { 517 return JDWP.EventKind.MONITOR_WAIT; 518 } 519 toString()520 public String toString() { 521 return "monitor wait request " + state(); 522 } 523 } 524 525 class MonitorWaitedRequestImpl extends ClassVisibleEventRequestImpl 526 implements MonitorWaitedRequest { MonitorWaitedRequestImpl()527 MonitorWaitedRequestImpl() { 528 requestList().add(this); 529 } 530 eventCmd()531 int eventCmd() { 532 return JDWP.EventKind.MONITOR_WAITED; 533 } 534 toString()535 public String toString() { 536 return "monitor waited request " + state(); 537 } 538 } 539 540 class StepRequestImpl extends ClassVisibleEventRequestImpl 541 implements StepRequest { 542 ThreadReferenceImpl thread; 543 int size; 544 int depth; 545 StepRequestImpl(ThreadReference thread, int size, int depth)546 StepRequestImpl(ThreadReference thread, int size, int depth) { 547 this.thread = (ThreadReferenceImpl)thread; 548 this.size = size; 549 this.depth = depth; 550 551 /* 552 * Translate size and depth to corresponding JDWP values. 553 */ 554 int jdwpSize; 555 switch (size) { 556 case STEP_MIN: 557 jdwpSize = JDWP.StepSize.MIN; 558 break; 559 case STEP_LINE: 560 jdwpSize = JDWP.StepSize.LINE; 561 break; 562 default: 563 throw new IllegalArgumentException("Invalid step size"); 564 } 565 566 int jdwpDepth; 567 switch (depth) { 568 case STEP_INTO: 569 jdwpDepth = JDWP.StepDepth.INTO; 570 break; 571 case STEP_OVER: 572 jdwpDepth = JDWP.StepDepth.OVER; 573 break; 574 case STEP_OUT: 575 jdwpDepth = JDWP.StepDepth.OUT; 576 break; 577 default: 578 throw new IllegalArgumentException("Invalid step depth"); 579 } 580 581 /* 582 * Make sure this isn't a duplicate 583 */ 584 List<StepRequest> requests = stepRequests(); 585 Iterator<StepRequest> iter = requests.iterator(); 586 while (iter.hasNext()) { 587 StepRequest request = iter.next(); 588 if ((request != this) && 589 request.isEnabled() && 590 request.thread().equals(thread)) { 591 throw new DuplicateRequestException( 592 "Only one step request allowed per thread"); 593 } 594 } 595 596 filters.add(JDWP.EventRequest.Set.Modifier.Step. 597 create(this.thread, jdwpSize, jdwpDepth)); 598 requestList().add(this); 599 600 } depth()601 public int depth() { 602 return depth; 603 } 604 size()605 public int size() { 606 return size; 607 } 608 thread()609 public ThreadReference thread() { 610 return thread; 611 } 612 eventCmd()613 int eventCmd() { 614 return JDWP.EventKind.SINGLE_STEP; 615 } 616 toString()617 public String toString() { 618 return "step request " + thread() + state(); 619 } 620 } 621 622 class ThreadDeathRequestImpl extends ThreadVisibleEventRequestImpl 623 implements ThreadDeathRequest { ThreadDeathRequestImpl()624 ThreadDeathRequestImpl() { 625 requestList().add(this); 626 } 627 eventCmd()628 int eventCmd() { 629 return JDWP.EventKind.THREAD_DEATH; 630 } 631 toString()632 public String toString() { 633 return "thread death request " + state(); 634 } 635 } 636 637 class ThreadStartRequestImpl extends ThreadVisibleEventRequestImpl 638 implements ThreadStartRequest { ThreadStartRequestImpl()639 ThreadStartRequestImpl() { 640 requestList().add(this); 641 } 642 eventCmd()643 int eventCmd() { 644 return JDWP.EventKind.THREAD_START; 645 } 646 toString()647 public String toString() { 648 return "thread start request " + state(); 649 } 650 } 651 652 abstract class WatchpointRequestImpl extends ClassVisibleEventRequestImpl 653 implements WatchpointRequest { 654 final Field field; 655 WatchpointRequestImpl(Field field)656 WatchpointRequestImpl(Field field) { 657 this.field = field; 658 filters.add(0, 659 JDWP.EventRequest.Set.Modifier.FieldOnly.create( 660 (ReferenceTypeImpl)field.declaringType(), 661 ((FieldImpl)field).ref())); 662 } 663 field()664 public Field field() { 665 return field; 666 } 667 } 668 669 class AccessWatchpointRequestImpl extends WatchpointRequestImpl 670 implements AccessWatchpointRequest { AccessWatchpointRequestImpl(Field field)671 AccessWatchpointRequestImpl(Field field) { 672 super(field); 673 requestList().add(this); 674 } 675 eventCmd()676 int eventCmd() { 677 return JDWP.EventKind.FIELD_ACCESS; 678 } 679 toString()680 public String toString() { 681 return "access watchpoint request " + field + state(); 682 } 683 } 684 685 class ModificationWatchpointRequestImpl extends WatchpointRequestImpl 686 implements ModificationWatchpointRequest { ModificationWatchpointRequestImpl(Field field)687 ModificationWatchpointRequestImpl(Field field) { 688 super(field); 689 requestList().add(this); 690 } 691 eventCmd()692 int eventCmd() { 693 return JDWP.EventKind.FIELD_MODIFICATION; 694 } 695 toString()696 public String toString() { 697 return "modification watchpoint request " + field + state(); 698 } 699 } 700 701 class VMDeathRequestImpl extends EventRequestImpl 702 implements VMDeathRequest { VMDeathRequestImpl()703 VMDeathRequestImpl() { 704 requestList().add(this); 705 } 706 eventCmd()707 int eventCmd() { 708 return JDWP.EventKind.VM_DEATH; 709 } 710 toString()711 public String toString() { 712 return "VM death request " + state(); 713 } 714 } 715 716 /** 717 * Constructor. 718 */ EventRequestManagerImpl(VirtualMachine vm)719 EventRequestManagerImpl(VirtualMachine vm) { 720 super(vm); 721 java.lang.reflect.Field[] ekinds = 722 JDWP.EventKind.class.getDeclaredFields(); 723 int highest = 0; 724 for (int i = 0; i < ekinds.length; ++i) { 725 int val; 726 try { 727 val = ekinds[i].getInt(null); 728 } catch (IllegalAccessException exc) { 729 throw new RuntimeException("Got: " + exc); 730 } 731 if (val > highest) { 732 highest = val; 733 } 734 } 735 requestLists = new List[highest+1]; 736 for (int i=0; i <= highest; i++) { 737 requestLists[i] = new ArrayList<>(); 738 } 739 } 740 createClassPrepareRequest()741 public ClassPrepareRequest createClassPrepareRequest() { 742 return new ClassPrepareRequestImpl(); 743 } 744 createClassUnloadRequest()745 public ClassUnloadRequest createClassUnloadRequest() { 746 return new ClassUnloadRequestImpl(); 747 } 748 createExceptionRequest(ReferenceType refType, boolean notifyCaught, boolean notifyUncaught)749 public ExceptionRequest createExceptionRequest(ReferenceType refType, 750 boolean notifyCaught, 751 boolean notifyUncaught) { 752 validateMirrorOrNull(refType); 753 return new ExceptionRequestImpl(refType, notifyCaught, notifyUncaught); 754 } 755 createStepRequest(ThreadReference thread, int size, int depth)756 public StepRequest createStepRequest(ThreadReference thread, 757 int size, int depth) { 758 validateMirror(thread); 759 return new StepRequestImpl(thread, size, depth); 760 } 761 createThreadDeathRequest()762 public ThreadDeathRequest createThreadDeathRequest() { 763 return new ThreadDeathRequestImpl(); 764 } 765 createThreadStartRequest()766 public ThreadStartRequest createThreadStartRequest() { 767 return new ThreadStartRequestImpl(); 768 } 769 createMethodEntryRequest()770 public MethodEntryRequest createMethodEntryRequest() { 771 return new MethodEntryRequestImpl(); 772 } 773 createMethodExitRequest()774 public MethodExitRequest createMethodExitRequest() { 775 return new MethodExitRequestImpl(); 776 } 777 createMonitorContendedEnterRequest()778 public MonitorContendedEnterRequest createMonitorContendedEnterRequest() { 779 if (!vm.canRequestMonitorEvents()) { 780 throw new UnsupportedOperationException( 781 "target VM does not support requesting Monitor events"); 782 } 783 return new MonitorContendedEnterRequestImpl(); 784 } 785 createMonitorContendedEnteredRequest()786 public MonitorContendedEnteredRequest createMonitorContendedEnteredRequest() { 787 if (!vm.canRequestMonitorEvents()) { 788 throw new UnsupportedOperationException( 789 "target VM does not support requesting Monitor events"); 790 } 791 return new MonitorContendedEnteredRequestImpl(); 792 } 793 createMonitorWaitRequest()794 public MonitorWaitRequest createMonitorWaitRequest() { 795 if (!vm.canRequestMonitorEvents()) { 796 throw new UnsupportedOperationException( 797 "target VM does not support requesting Monitor events"); 798 } 799 return new MonitorWaitRequestImpl(); 800 } 801 createMonitorWaitedRequest()802 public MonitorWaitedRequest createMonitorWaitedRequest() { 803 if (!vm.canRequestMonitorEvents()) { 804 throw new UnsupportedOperationException( 805 "target VM does not support requesting Monitor events"); 806 } 807 return new MonitorWaitedRequestImpl(); 808 } 809 createBreakpointRequest(Location location)810 public BreakpointRequest createBreakpointRequest(Location location) { 811 validateMirror(location); 812 if (location.codeIndex() == -1) { 813 throw new NativeMethodException("Cannot set breakpoints on native methods"); 814 } 815 return new BreakpointRequestImpl(location); 816 } 817 818 public AccessWatchpointRequest createAccessWatchpointRequest(Field field)819 createAccessWatchpointRequest(Field field) { 820 validateMirror(field); 821 if (!vm.canWatchFieldAccess()) { 822 throw new UnsupportedOperationException( 823 "target VM does not support access watchpoints"); 824 } 825 return new AccessWatchpointRequestImpl(field); 826 } 827 828 public ModificationWatchpointRequest createModificationWatchpointRequest(Field field)829 createModificationWatchpointRequest(Field field) { 830 validateMirror(field); 831 if (!vm.canWatchFieldModification()) { 832 throw new UnsupportedOperationException( 833 "target VM does not support modification watchpoints"); 834 } 835 return new ModificationWatchpointRequestImpl(field); 836 } 837 createVMDeathRequest()838 public VMDeathRequest createVMDeathRequest() { 839 if (!vm.canRequestVMDeathEvent()) { 840 throw new UnsupportedOperationException( 841 "target VM does not support requesting VM death events"); 842 } 843 return new VMDeathRequestImpl(); 844 } 845 deleteEventRequest(EventRequest eventRequest)846 public void deleteEventRequest(EventRequest eventRequest) { 847 validateMirror(eventRequest); 848 ((EventRequestImpl)eventRequest).delete(); 849 } 850 deleteEventRequests(List<? extends EventRequest> eventRequests)851 public void deleteEventRequests(List<? extends EventRequest> eventRequests) { 852 validateMirrors(eventRequests); 853 // copy the eventRequests to avoid ConcurrentModificationException 854 Iterator<? extends EventRequest> iter = (new ArrayList<>(eventRequests)).iterator(); 855 while (iter.hasNext()) { 856 ((EventRequestImpl)iter.next()).delete(); 857 } 858 } 859 deleteAllBreakpoints()860 public void deleteAllBreakpoints() { 861 requestList(JDWP.EventKind.BREAKPOINT).clear(); 862 863 try { 864 JDWP.EventRequest.ClearAllBreakpoints.process(vm); 865 } catch (JDWPException exc) { 866 throw exc.toJDIException(); 867 } 868 } 869 stepRequests()870 public List<StepRequest> stepRequests() { 871 return (List<StepRequest>)unmodifiableRequestList(JDWP.EventKind.SINGLE_STEP); 872 } 873 classPrepareRequests()874 public List<ClassPrepareRequest> classPrepareRequests() { 875 return (List<ClassPrepareRequest>)unmodifiableRequestList(JDWP.EventKind.CLASS_PREPARE); 876 } 877 classUnloadRequests()878 public List<ClassUnloadRequest> classUnloadRequests() { 879 return (List<ClassUnloadRequest>)unmodifiableRequestList(JDWP.EventKind.CLASS_UNLOAD); 880 } 881 threadStartRequests()882 public List<ThreadStartRequest> threadStartRequests() { 883 return (List<ThreadStartRequest>)unmodifiableRequestList(JDWP.EventKind.THREAD_START); 884 } 885 threadDeathRequests()886 public List<ThreadDeathRequest> threadDeathRequests() { 887 return (List<ThreadDeathRequest>)unmodifiableRequestList(JDWP.EventKind.THREAD_DEATH); 888 } 889 exceptionRequests()890 public List<ExceptionRequest> exceptionRequests() { 891 return (List<ExceptionRequest>)unmodifiableRequestList(JDWP.EventKind.EXCEPTION); 892 } 893 breakpointRequests()894 public List<BreakpointRequest> breakpointRequests() { 895 return (List<BreakpointRequest>)unmodifiableRequestList(JDWP.EventKind.BREAKPOINT); 896 } 897 accessWatchpointRequests()898 public List<AccessWatchpointRequest> accessWatchpointRequests() { 899 return (List<AccessWatchpointRequest>)unmodifiableRequestList(JDWP.EventKind.FIELD_ACCESS); 900 } 901 modificationWatchpointRequests()902 public List<ModificationWatchpointRequest> modificationWatchpointRequests() { 903 return (List<ModificationWatchpointRequest>)unmodifiableRequestList(JDWP.EventKind.FIELD_MODIFICATION); 904 } 905 methodEntryRequests()906 public List<MethodEntryRequest> methodEntryRequests() { 907 return (List<MethodEntryRequest>)unmodifiableRequestList(JDWP.EventKind.METHOD_ENTRY); 908 } 909 methodExitRequests()910 public List<MethodExitRequest> methodExitRequests() { 911 return (List<MethodExitRequest>)unmodifiableRequestList( 912 EventRequestManagerImpl.methodExitEventCmd); 913 } 914 monitorContendedEnterRequests()915 public List<MonitorContendedEnterRequest> monitorContendedEnterRequests() { 916 return (List<MonitorContendedEnterRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_CONTENDED_ENTER); 917 } 918 monitorContendedEnteredRequests()919 public List<MonitorContendedEnteredRequest> monitorContendedEnteredRequests() { 920 return (List<MonitorContendedEnteredRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_CONTENDED_ENTERED); 921 } 922 monitorWaitRequests()923 public List<MonitorWaitRequest> monitorWaitRequests() { 924 return (List<MonitorWaitRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_WAIT); 925 } 926 monitorWaitedRequests()927 public List<MonitorWaitedRequest> monitorWaitedRequests() { 928 return (List<MonitorWaitedRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_WAITED); 929 } 930 vmDeathRequests()931 public List<VMDeathRequest> vmDeathRequests() { 932 return (List<VMDeathRequest>)unmodifiableRequestList(JDWP.EventKind.VM_DEATH); 933 } 934 unmodifiableRequestList(int eventCmd)935 List<? extends EventRequest> unmodifiableRequestList(int eventCmd) { 936 return Collections.unmodifiableList(requestList(eventCmd)); 937 } 938 request(int eventCmd, int requestId)939 EventRequest request(int eventCmd, int requestId) { 940 List<? extends EventRequest> rl = requestList(eventCmd); 941 for (int i = rl.size() - 1; i >= 0; i--) { 942 EventRequestImpl er = (EventRequestImpl)rl.get(i); 943 if (er.id == requestId) { 944 return er; 945 } 946 } 947 return null; 948 } 949 requestList(int eventCmd)950 List<? extends EventRequest> requestList(int eventCmd) { 951 return requestLists[eventCmd]; 952 } 953 954 } 955