Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Debugee.java
41161 views
1
/*
2
* Copyright (c) 2001, 2021, 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
package nsk.share.jdwp;
25
26
import nsk.share.*;
27
import nsk.share.jpda.*;
28
29
import java.util.*;
30
import java.io.*;
31
32
/**
33
* This class is used to interact with debugee VM using JDWP features.
34
* <p>
35
* This class is an mirror of debugee VM that is constructed by
36
* <code>Binder</code> and uses <code>Transport</code> object
37
* to interact with debugee VM.
38
* <p>
39
* In addition to the general abities to control of debugee VM process,
40
* provided by the base class <code>DebugeeProcess</code>, this class
41
* adds some service methods that uses JDWP protocol to simplify interaction
42
* with debugee VM (such as finding classes, setting breakpoints,
43
* handling events, and so on.).
44
*
45
* @see Binder
46
* @see Transport
47
* @see DebugeeProcess
48
*/
49
abstract public class Debugee extends DebugeeProcess {
50
51
/** Binder that creates this debugee. */
52
protected Binder binder = null;
53
54
protected LinkedList<EventPacket> eventQueue = new LinkedList<EventPacket>();
55
56
protected Transport transport = null;
57
58
/** Make new <code>Debugee</code> object for the given binder. */
59
protected Debugee (Binder binder) {
60
super(binder);
61
this.argumentHandler = binder.getArgumentHandler();
62
this.binder = binder;
63
prefix = "Debugee> ";
64
}
65
66
/** Return <code>Binder</code> of the debugee object. */
67
public Binder getBinder() {
68
return binder;
69
}
70
71
/** Return <code>Transport</code> of the debugee object. */
72
public Transport getTransport() {
73
return transport;
74
}
75
76
/**
77
* Prepare transport object for establishing connection.
78
* This may change connection options in <code>argumentHandler</code>.
79
*
80
* @return specific address string if listening has started or null otherwise
81
*/
82
public String prepareTransport(ArgumentHandler argumentHandler) {
83
String address = null;
84
try {
85
if (argumentHandler.isSocketTransport()) {
86
SocketTransport socket_transport = new SocketTransport(log);
87
if (argumentHandler.isListeningConnector()) {
88
int port = 0;
89
if (argumentHandler.isTransportAddressDynamic()) {
90
port = socket_transport.bind(0);
91
// argumentHandler.setTransportPortNumber(port);
92
} else {
93
port = argumentHandler.getTransportPortNumber();
94
socket_transport.bind(port);
95
}
96
address = argumentHandler.getTestHost() + ":" + port;
97
}
98
transport = socket_transport;
99
/*
100
} else if (argumentHandler.isShmemTransport()) {
101
ShmemTransport shmem_transport = new ShmemTransport(log);
102
if (argumentHandler.isListeningConnector()) {
103
String sharedName = agrHandler.getTransportSharedName();
104
shmem_transport.bind(sharedName);
105
address = sharedName;
106
}
107
transport = shmem_transport;
108
*/
109
} else {
110
throw new TestBug("Unexpected transport type: "
111
+ argumentHandler.getTransportType());
112
}
113
114
} catch (IOException e) {
115
e.printStackTrace(log.getOutStream());
116
throw new Failure("Caught IOException while preparing for JDWP transport connection:\n\t"
117
+ e);
118
}
119
120
return address;
121
}
122
123
/**
124
* Establish connection to debugee VM.
125
*/
126
public Transport connect() {
127
if (transport == null) {
128
throw new Failure("Attemt to establish JDWP connection for not prepared transport");
129
}
130
131
try {
132
if (argumentHandler.isSocketTransport()) {
133
display("Establishing JDWP socket connection");
134
SocketTransport socket_transport = (SocketTransport)transport;
135
int transportPort = argumentHandler.getTransportPortNumber();
136
if (argumentHandler.isAttachingConnector()) {
137
String debugeeHost = argumentHandler.getDebugeeHost();
138
display("Attaching to debugee: " + debugeeHost + ":" + transportPort);
139
socket_transport.attach(debugeeHost, transportPort);
140
} else if (argumentHandler.isListeningConnector()) {
141
display("Listening from debugee");
142
socket_transport.accept();
143
} else {
144
throw new TestBug("Unexpected connector type: "
145
+ argumentHandler.getConnectorType());
146
}
147
/*
148
} else if (argumentHandler.isShmemTransport()) {
149
display("Establishing JDWP shared-memory connection");
150
ShmemTransport shmem_transport = (ShmemTransport)transport;
151
String sharedName = argumentHandler.getTransportSharedName();
152
if (argumentHandler.isAttachingConnector()) {
153
display("Attaching to debugee: " + sharedName);
154
shmem_transport.attach(sharedName);
155
} else if (argumentHandler.isListeningConnector()) {
156
display("Listening from debugee");
157
shmem_transport.accept();
158
} else {
159
throw new TestBug("Unexpected connector type: "
160
+ argumentHandler.getConnectorType());
161
}
162
*/
163
} else {
164
throw new TestBug("Unexpected transport type: "
165
+ argumentHandler.getTransportType());
166
}
167
168
transport.handshake();
169
170
} catch (IOException e) {
171
e.printStackTrace(log.getOutStream());
172
throw new Failure("Caught IOException while establishing JDWP transport connection:\n\t"
173
+ e);
174
}
175
return transport;
176
}
177
178
// --------------------------------------------------- //
179
180
/**
181
* Waits for VM_INIT event from debugee VM.
182
*/
183
public void waitForVMInit() {
184
String eventName = "VirtualMachine.VM_START";
185
EventPacket packet = receiveEventFor(JDWP.EventKind.VM_START, eventName);
186
// String versionInfo = getVersionInfo();
187
// display("Target VM started:\n" + versionInfo);
188
}
189
190
/**
191
* Waits for VM_DEATH event from debugee VM.
192
*/
193
public void waitForVMDeath() {
194
String eventName = "VirtualMachine.VM_DEATH";
195
EventPacket packet = receiveEventFor(JDWP.EventKind.VM_DEATH, eventName);
196
}
197
198
/**
199
* Wait for class loaded on debugee start up and return its classID.
200
* Debuggee should be initially suspended and it will also left suspended
201
* by the CLASS_PREPARE event request.
202
*/
203
public long waitForClassLoaded(String className, byte suspendPolicy) {
204
// make request for CLASS_PREPARE_EVENT for this class name
205
int requestID = requestClassPrepareEvent(className, suspendPolicy);
206
// resume initially suspended debugee
207
resume();
208
// wait for CLASS_PREPARE_EVENT
209
return waitForClassPrepareEvent(requestID, className);
210
}
211
212
/**
213
* Wait for classes loaded on debugee start up and return their classIDs.
214
* Debuggee should be initially suspended and it will also left suspended
215
* by the CLASS_PREPARE event request.
216
*/
217
public long[] waitForClassesLoaded(String classNames[], byte suspendPolicy) {
218
int count = classNames.length;
219
220
// make requests for CLASS_PREPARE_EVENT for these class names
221
int[] requestIDs = new int[count];
222
for (int i = 0; i < count; i++) {
223
requestIDs[i] = requestClassPrepareEvent(classNames[i], suspendPolicy);
224
}
225
226
// resume initially suspended debugee
227
resume();
228
229
return waitForClassPrepareEvents(requestIDs, classNames);
230
}
231
232
/**
233
* Wait for breakpoint reached and return threadIDs.
234
* Debuggee should be initially suspended and it will also left suspended
235
* by the BREAKPOINT event request.
236
*/
237
public long waitForBreakpointReached(long classID, String methodName,
238
int line, byte suspendPolicy) {
239
// query debuggee for methodID
240
long methodID = getMethodID(classID, methodName, true);
241
// create BREAKPOINT event request
242
int requestID = requestBreakpointEvent(JDWP.TypeTag.CLASS, classID, methodID,
243
line, suspendPolicy);
244
// resume initially suspended debugee
245
resume();
246
// wait for BREAKPOINT event
247
return waitForBreakpointEvent(requestID);
248
}
249
250
// --------------------------------------------------- //
251
252
/**
253
* Wait for CLASS_PREPARE event made by given request received
254
* and return classID.
255
* Debuggee will be left suspended by the CLASS_PREPARE event.
256
*/
257
public long waitForClassPrepareEvent(int requestID, String className) {
258
String error = "Error occured while waiting for CLASS_PREPARE event for class:\n\t"
259
+ className;
260
261
String signature = "L" + className.replace('.', '/') + ";";
262
long classID = 0;
263
264
// wait for CLASS_PREPARE event
265
for(;;) {
266
EventPacket event = receiveEvent();
267
byte eventSuspendPolicy = 0;
268
long eventThreadID = 0;
269
try {
270
eventSuspendPolicy = event.getByte();
271
int events = event.getInt();
272
for (int i = 0; i < events; i++) {
273
// check event kind
274
byte eventKind = event.getByte();
275
if (eventKind == JDWP.EventKind.VM_DEATH) {
276
complain("Unexpected VM_DEATH event received: " + eventKind
277
+ " (expected: " + JDWP.EventKind.CLASS_PREPARE +")");
278
throw new Failure(error);
279
} else if (eventKind != JDWP.EventKind.CLASS_PREPARE) {
280
complain("Unexpected event kind received: " + eventKind
281
+ " (expected: " + JDWP.EventKind.CLASS_PREPARE +")");
282
throw new Failure(error);
283
}
284
285
// extract CLASS_PREPARE event specific data
286
int eventRequestID = event.getInt();
287
eventThreadID = event.getObjectID();
288
byte eventRefTypeTag = event.getByte();
289
long eventClassID = event.getReferenceTypeID();
290
String eventClassSignature = event.getString();
291
int eventClassStatus = event.getInt();
292
293
// check if event was single
294
if (events > 1) {
295
complain("Not single CLASS_PREPARE event received for class:\n\t"
296
+ eventClassSignature);
297
throw new Failure(error);
298
}
299
300
// check if event is for expected class
301
if (eventClassSignature.equals(signature)) {
302
303
// check if event is because of expected request
304
if (eventRequestID != requestID) {
305
complain("CLASS_PREPARE event with unexpected requestID ("
306
+ eventRequestID + ") received for class:\n\t"
307
+ eventClassSignature);
308
throw new Failure(error);
309
}
310
311
// remove event request
312
clearEventRequest(JDWP.EventKind.CLASS_PREPARE, requestID);
313
314
return eventClassID;
315
} else {
316
complain("Unexpected CLASS_PREPARE event received with class signature:\n"
317
+ " " + eventClassSignature);
318
}
319
320
}
321
322
} catch (BoundException e) {
323
complain("Unable to extract data from event packet while waiting for CLASS_PREPARE event:\n\t"
324
+ e.getMessage() + "\n" + event);
325
throw new Failure(error);
326
}
327
328
// resume debuggee according to event suspend policy
329
resumeEvent(eventSuspendPolicy, eventThreadID);
330
}
331
}
332
333
/**
334
* Wait for CLASS_PREPARE events made by given requests received
335
* and return classIDs.
336
* Debuggee will be left suspended by the CLASS_PREPARE event.
337
*/
338
public long[] waitForClassPrepareEvents(int requestIDs[], String classNames[]) {
339
int count = classNames.length;
340
String error = "Error occured while waiting for " + count + " CLASS_PREPARE events";
341
342
// prepare expected class signatures
343
String[] signatures = new String[count];
344
for (int i = 0; i < count; i++) {
345
signatures[i] = "L" + classNames[i].replace('.', '/') + ";";
346
}
347
348
// clear list of classIDs
349
long[] classIDs = new long[count];
350
for (int i = 0; i < count; i++) {
351
classIDs[i] = 0;
352
}
353
354
// wait for all expected CLASS_PREPARE events
355
int received = 0;
356
for(;;) {
357
EventPacket event = receiveEvent();
358
byte eventSuspendPolicy = 0;
359
long eventThreadID = 0;
360
try {
361
eventSuspendPolicy = event.getByte();
362
int events = event.getInt();
363
for (int i = 0; i < events; i++) {
364
// check event kind
365
byte eventKind = event.getByte();
366
if (eventKind == JDWP.EventKind.VM_DEATH) {
367
complain("Unexpected VM_DEATH event received: " + eventKind
368
+ " (expected: " + JDWP.EventKind.CLASS_PREPARE +")");
369
throw new Failure(error);
370
} else if (eventKind != JDWP.EventKind.CLASS_PREPARE) {
371
complain("Unexpected event kind received: " + eventKind
372
+ " (expected: " + JDWP.EventKind.CLASS_PREPARE +")");
373
throw new Failure(error);
374
}
375
376
// extracy CLASS_PREPARE event specific data
377
int eventRequestID = event.getInt();
378
eventThreadID = event.getObjectID();
379
byte eventRefTypeTag = event.getByte();
380
long eventClassID = event.getReferenceTypeID();
381
String eventClassSignature = event.getString();
382
int eventClassStatus = event.getInt();
383
384
// check if event was single
385
if (events > 1) {
386
complain("Not single CLASS_PREPARE event received for class:\n\t"
387
+ eventClassSignature);
388
}
389
390
// find appropriate class by signature
391
boolean found = false;
392
for (int j = 0; j < count; j++) {
393
if (eventClassSignature.equals(signatures[j])) {
394
found = true;
395
396
// check if event is not duplicated
397
if (classIDs[j] != 0) {
398
complain("Extra CLASS_PREPARE event recieved for class:\n\t"
399
+ eventClassSignature);
400
} else {
401
classIDs[j] = eventClassID;
402
received ++;
403
}
404
405
// check if event is because of expected request
406
if (eventRequestID != requestIDs[j]) {
407
complain("CLASS_PREPARE event with unexpected requestID ("
408
+ requestIDs[j] + ") received for class:\n\t"
409
+ eventClassSignature);
410
} else {
411
clearEventRequest(JDWP.EventKind.CLASS_PREPARE, requestIDs[j]);
412
}
413
}
414
}
415
if (!found) {
416
log.complain("Unexpected CLASS_PREPARE event received with class signature:\n"
417
+ " " + eventClassSignature);
418
}
419
}
420
} catch (BoundException e) {
421
complain("Unable to extract data from event packet while waiting for CLASS_PREPARE event:\n\t"
422
+ e.getMessage() + "\n" + event);
423
throw new Failure(error);
424
}
425
426
// if all events received return without resuming
427
if (received >= count)
428
return classIDs;
429
430
// resume debuggee according to events suspend policy
431
resumeEvent(eventSuspendPolicy, eventThreadID);
432
}
433
}
434
435
/**
436
* Wait for BREAKPOINT event made by the given request and return threadID.
437
* Debuggee will be left suspended by the BREAKPOINT event.
438
*/
439
public long waitForBreakpointEvent(int requestID) {
440
String error = "Error occured while waiting for BREAKPOINT event for ";
441
442
for(;;) {
443
EventPacket event = receiveEvent();
444
byte eventSuspendPolicy = 0;
445
long eventThreadID = 0;
446
try {
447
eventSuspendPolicy = event.getByte();
448
int events = event.getInt();
449
for (int i = 0; i < events; i++) {
450
// check event kind
451
byte eventKind = event.getByte();
452
if (eventKind == JDWP.EventKind.VM_DEATH) {
453
complain("Unexpected VM_DEATH event received: " + eventKind
454
+ " (expected: " + JDWP.EventKind.BREAKPOINT +")");
455
throw new Failure(error);
456
} else if (eventKind != JDWP.EventKind.BREAKPOINT) {
457
complain("Unexpected event kind received: " + eventKind
458
+ " (expected: " + JDWP.EventKind.BREAKPOINT +")");
459
throw new Failure(error);
460
}
461
462
// extrack specific BREAKPOINT event data
463
int eventRequestID = event.getInt();
464
eventThreadID = event.getObjectID();
465
JDWP.Location eventLocation = event.getLocation();
466
467
if (eventRequestID == requestID) {
468
clearEventRequest(JDWP.EventKind.BREAKPOINT, requestID);
469
return eventThreadID;
470
} else {
471
complain("Unexpected BREAKPOINT event received with requestID: "
472
+ eventRequestID + " (expected: " + requestID + ")");
473
}
474
}
475
} catch (BoundException e) {
476
complain("Unable to extract data from event packet while waiting for BREAKPOINT event:\n\t"
477
+ e.getMessage() + "\n" + event);
478
throw new Failure(error);
479
}
480
481
resumeEvent(eventSuspendPolicy, eventThreadID);
482
}
483
}
484
485
/**
486
* Resume debuggee according given event suspend policy.
487
*/
488
public void resumeEvent(byte suspendPolicy, long threadID) {
489
if (suspendPolicy == JDWP.SuspendPolicy.NONE) {
490
// do nothing
491
} else if (suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) {
492
resumeThread(threadID);
493
} else if (suspendPolicy == JDWP.SuspendPolicy.ALL) {
494
resume();
495
} else {
496
throw new Failure("Unexpected event suspend policy while resuming debuggee: "
497
+ suspendPolicy);
498
}
499
}
500
501
// --------------------------------------------------- //
502
503
/**
504
* Query target VM for version info.
505
*/
506
public String getVersionInfo() {
507
String commandName = "VirtualMachine.Version";
508
CommandPacket command =
509
new CommandPacket(JDWP.Command.VirtualMachine.Version);
510
ReplyPacket reply = receiveReplyFor(command, commandName);
511
512
try {
513
String description = reply.getString();
514
int jdwpMajor = reply.getInt();
515
int jdwpMinor = reply.getInt();
516
String vmVersion = reply.getString();
517
String vmName = reply.getString();
518
return description;
519
} catch (BoundException e) {
520
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
521
+ e.getMessage());
522
display("Reply packet:\n" + reply);
523
throw new Failure("Error occured while getting JDWP and VM version info");
524
}
525
}
526
527
/**
528
* Query target VM about VM dependent ID sizes.
529
*/
530
public void queryForIDSizes() {
531
String commandName = "VirtualMachine.IDSizes";
532
CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.IDSizes);
533
ReplyPacket reply = receiveReplyFor(command);
534
try {
535
reply.resetPosition();
536
JDWP.TypeSize.FIELD_ID = reply.getInt();
537
JDWP.TypeSize.METHOD_ID = reply.getInt();
538
JDWP.TypeSize.OBJECT_ID = reply.getInt();
539
JDWP.TypeSize.REFERENCE_TYPE_ID = reply.getInt();
540
JDWP.TypeSize.FRAME_ID = reply.getInt();
541
} catch (BoundException e) {
542
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
543
+ e.getMessage());
544
display("Reply packet:\n" + reply);
545
throw new Failure("Error occured while getting VM dependent ID sizes");
546
}
547
JDWP.TypeSize.CalculateSizes();
548
}
549
550
// --------------------------------------------------- //
551
552
/**
553
* Suspend the debugee VM by sending VirtualMachine.Suspend command.
554
*/
555
public void suspend() {
556
String commandName = "VirtualMachine.Suspend";
557
CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.Suspend);
558
ReplyPacket reply = receiveReplyFor(command, commandName);
559
}
560
561
/**
562
* Resume the debugee VM by sending VirtualMachine.Resume command.
563
*/
564
public void resume() {
565
String commandName = "VirtualMachine.Resume";
566
CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.Resume);
567
ReplyPacket reply = receiveReplyFor(command, commandName);
568
}
569
570
/**
571
* Dispose the debugee VM by sending VirtualMachine.Dispose command.
572
*/
573
public void dispose() {
574
String commandName = "VirtualMachine.Dispose";
575
CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.Dispose);
576
ReplyPacket reply = receiveReplyFor(command, commandName);
577
}
578
579
// --------------------------------------------------- //
580
581
/**
582
* Sends JDWP command packet.
583
*/
584
public void sendCommand(CommandPacket packet, String commandName) {
585
try {
586
transport.write(packet);
587
} catch (IOException e) {
588
e.printStackTrace(log.getOutStream());
589
complain("Caught IOException while sending command packet for "
590
+ commandName + ":\n\t" + e);
591
display("Command packet:\n" + packet);
592
throw new Failure("Error occured while sending command: " + commandName);
593
}
594
}
595
596
/**
597
* Receive next JDWP packet.
598
*/
599
/*
600
public Packet receivePacket() {
601
try {
602
ReplyPacket packet = new ReplyPacket();
603
transport.read(packet);
604
return packet;
605
} catch (IOException e) {
606
e.printStackTrace(log.getOutStream());
607
throw new Failure("Caught IOException while receiving reply packet:\n\t" + e);
608
}
609
}
610
*/
611
/**
612
* Receive next JDWP reply packet.
613
*/
614
public ReplyPacket receiveReply() {
615
try {
616
for (;;) {
617
Packet packet = new Packet();
618
transport.read(packet);
619
620
if (packet.getFlags() == JDWP.Flag.REPLY_PACKET) {
621
ReplyPacket reply = new ReplyPacket(packet);
622
return reply;
623
}
624
625
EventPacket event = new EventPacket(packet);
626
display("Placing received event packet into queue");
627
eventQueue.add(event);
628
}
629
} catch (IOException e) {
630
e.printStackTrace(log.getOutStream());
631
throw new Failure("Caught IOException while receiving reply packet:\n\t" + e);
632
}
633
}
634
635
/**
636
* Get next JDWP event packet by reading from transport or getting stored
637
* event in the event queue.
638
*/
639
public EventPacket getEventPacket() throws IOException {
640
// check events queue first
641
if (!eventQueue.isEmpty()) {
642
EventPacket event = (EventPacket)(eventQueue.removeFirst());
643
return event;
644
}
645
646
// read from transport
647
Packet packet = new Packet();
648
transport.read(packet);
649
650
EventPacket event = new EventPacket(packet);
651
return event;
652
}
653
654
/**
655
* Get next JDWP event packet by reading from transport for specified timeout
656
* or getting stored event in the event queue.
657
*/
658
public EventPacket getEventPacket(long timeout) throws IOException {
659
transport.setReadTimeout(timeout);
660
return getEventPacket();
661
}
662
663
/**
664
* Receive next JDWP event packet.
665
*/
666
public EventPacket receiveEvent() {
667
EventPacket packet = null;
668
try {
669
packet = getEventPacket();
670
} catch (IOException e) {
671
e.printStackTrace(log.getOutStream());
672
throw new Failure("Caught IOException while receiving event packet:\n\t" + e);
673
}
674
675
if (packet.getFlags() == JDWP.Flag.REPLY_PACKET) {
676
ReplyPacket reply = new ReplyPacket(packet);
677
log.complain("Unexpected reply packet received with id: "
678
+ reply.getPacketID());
679
log.display("Reply packet:\n" + reply);
680
throw new Failure("Unexpected reply packet received instead of event packet");
681
}
682
683
return packet;
684
}
685
686
/**
687
* Send specified command packet, receive and check reply packet.
688
*
689
* @throws Failure if exception caught in sending and reading packets
690
*/
691
public ReplyPacket receiveReplyFor(CommandPacket command) {
692
return receiveReplyFor(command, Packet.toHexString(command.getCommand(), 4));
693
}
694
695
/**
696
* Send specified command packet, receive and check reply packet.
697
*
698
* @throws Failure if exception caught in sending and reading packets
699
*/
700
public ReplyPacket receiveReplyFor(CommandPacket command, String commandName) {
701
ReplyPacket reply = null;
702
sendCommand(command, commandName);
703
reply = receiveReply();
704
try {
705
reply.checkHeader(command.getPacketID());
706
} catch (BoundException e) {
707
complain("Wrong header of reply packet for command "+ commandName + ":\n\t"
708
+ e.getMessage());
709
display("Reply packet:\n" + reply);
710
throw new Failure("Wrong reply packet received for command: " + commandName);
711
}
712
return reply;
713
}
714
715
/**
716
* Receive and check event packet for specified event kind.
717
*
718
* @throws Failure if exception caught in sending and reading packets
719
*/
720
public EventPacket receiveEventFor(int eventKind, String eventName) {
721
EventPacket event = null;
722
event = receiveEvent();
723
try {
724
event.checkHeader(eventKind);
725
} catch (BoundException e) {
726
complain("Wrong header of event packet for expected "+ eventName + " event:\n\t"
727
+ e.getMessage());
728
display("Event packet:\n" + event);
729
throw new Failure("Wrong event packet received for expected event: " + eventName);
730
}
731
return event;
732
}
733
734
// --------------------------------------------------- //
735
736
/**
737
* Check common VM capability.
738
*/
739
public boolean getCapability(int capability, String name) {
740
String commandName = "VirtualMachine.Capabilities";
741
742
int count = JDWP.Capability.CAN_GET_MONITOR_INFO + 1;
743
if (capability < 0 || capability >= count) {
744
throw new TestBug("Illegal capability number (" + capability
745
+ ") while checking for VM capability: " + name);
746
}
747
748
CommandPacket command =
749
new CommandPacket(JDWP.Command.VirtualMachine.Capabilities);
750
ReplyPacket reply = receiveReplyFor(command, commandName);
751
752
try {
753
reply.resetPosition();
754
755
for (int i = 0; i < count; i++) {
756
byte value = reply.getByte();
757
if (i == capability) {
758
return (value != 0);
759
}
760
}
761
762
} catch (BoundException e) {
763
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
764
+ e.getMessage());
765
display("Reply packet:\n" + reply);
766
throw new Failure("Error occured while getting VM capability: "
767
+ name);
768
}
769
770
throw new TestBug("Illegal capability number (" + capability
771
+ ") while checking for VM capability: " + name);
772
}
773
774
/**
775
* Check new VM capability (since JDWP version 1.4).
776
*/
777
public boolean getNewCapability(int capability, String name) {
778
String commandName = "VirtualMachine.CapabilitiesNew";
779
int count = JDWP.Capability.CAN_SET_DEFAULT_STRATUM + 1;
780
781
if (capability < 0 || capability >= count) {
782
throw new TestBug("Illegal capability number (" + capability
783
+ ") while checking for VM new capability: " + name);
784
}
785
786
CommandPacket command =
787
new CommandPacket(JDWP.Command.VirtualMachine.CapabilitiesNew);
788
ReplyPacket reply = receiveReplyFor(command, commandName);
789
790
try {
791
reply.resetPosition();
792
793
for (int i = 0; i < count; i++) {
794
byte value = reply.getByte();
795
if (i == capability) {
796
return (value != 0);
797
}
798
}
799
} catch (BoundException e) {
800
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
801
+ e.getMessage());
802
display("Reply packet:\n" + reply);
803
throw new Failure("Error occured while getting VM new capability: "
804
+ name);
805
}
806
807
throw new TestBug("Illegal capability number (" + capability
808
+ ") while checking for VM new capability: " + name);
809
}
810
811
// --------------------------------------------------- //
812
813
/**
814
* Return ReferenceTypeID for requested class by given signature.
815
*/
816
public long getReferenceTypeID(String classSignature) {
817
String commandName = "VirtualMachine.ClassesBySignature";
818
CommandPacket command =
819
new CommandPacket(JDWP.Command.VirtualMachine.ClassesBySignature);
820
command.addString(classSignature);
821
command.setLength();
822
ReplyPacket reply = receiveReplyFor(command, commandName);
823
824
long typeID = 0;
825
826
try {
827
reply.resetPosition();
828
829
int classes = reply.getInt();
830
for (int i = 0; i < classes; i++) {
831
byte refTypeTag = reply.getByte();
832
typeID = reply.getReferenceTypeID();
833
int status = reply.getInt();
834
}
835
836
if (classes < 0) {
837
throw new Failure("Negative number (" + classes
838
+ ") of referenceTypeIDs received for signature: "
839
+ classSignature);
840
}
841
842
if (classes == 0) {
843
throw new Failure("No any referenceTypeID received for signature: "
844
+ classSignature);
845
}
846
847
if (classes > 1) {
848
throw new Failure("Too many (" + classes
849
+ ") referenceTypeIDs received for signature: "
850
+ classSignature);
851
}
852
853
} catch (BoundException e) {
854
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
855
+ e.getMessage());
856
display("Reply packet:\n" + reply);
857
throw new Failure("Error occured while getting referenceTypeID for signature: "
858
+ classSignature);
859
}
860
861
return typeID;
862
}
863
864
// --------------------------------------------------- //
865
866
867
/**
868
* Get list of IDs of supertypes (interfaces and classes) for given class.
869
*/
870
public long[] getSupertypes(long classID, boolean declared) {
871
Vector<Long> vector = new Vector<Long>();
872
addSupertypes(classID, vector, null, null, false, declared);
873
return makeListOfLongValues(vector);
874
}
875
876
/**
877
* Get list of IDs of superclasses for given class.
878
*/
879
public long[] getSuperclasses(long classID, boolean declared) {
880
Vector<Long> vector = new Vector<Long>();
881
addSupertypes(classID, null, null, vector, false, declared);
882
return makeListOfLongValues(vector);
883
}
884
885
/**
886
* Get list of IDs of implemented interfaces for given class.
887
*/
888
public long[] getImplementedInterfaces(long classID, boolean declared) {
889
Vector<Long> vector = new Vector<Long>();
890
addSupertypes(classID, null, vector, null, false, declared);
891
return makeListOfLongValues(vector);
892
}
893
894
/**
895
* Get list of IDs of superinterfaces for given interface.
896
*/
897
public long[] getSuperinterfaces(long interfaceID, boolean declared) {
898
Vector<Long> vector = new Vector<Long>();
899
addSupertypes(interfaceID, null, vector, null, true, declared);
900
return makeListOfLongValues(vector);
901
}
902
903
// --------------------------------------------------- //
904
905
/**
906
* Get list of IDs of methods of given class.
907
*/
908
public long[] getMethodIDs(long classID, boolean declared) {
909
Vector<Long> list = new Vector<Long>();
910
addMethods(classID, list, null, null, null, false, declared);
911
return makeListOfLongValues(list);
912
}
913
914
/**
915
* Get list of names of methods of given class.
916
*/
917
public String[] getMethodNames(long classID, boolean declared) {
918
Vector<String> list = new Vector<String>();
919
addMethods(classID, null, list, null, null, false, declared);
920
return makeListOfStringValues(list);
921
}
922
923
/**
924
* Get list of signatures of methods of given class.
925
*/
926
public String[] getMethodSignatures(long classID, boolean declared) {
927
Vector<String> list = new Vector<String>();
928
addMethods(classID, null, null, list, null, false, declared);
929
return makeListOfStringValues(list);
930
}
931
932
/**
933
* Get ID of a method of given class by name.
934
*/
935
public long getMethodID(long classID, String name, boolean declared) {
936
Vector<Long> IDs = new Vector<Long>();
937
Vector<String> names = new Vector<String>();
938
addMethods(classID, IDs, names, null, null, false, declared);
939
int count = names.size();
940
for (int i = 0; i < count; i++) {
941
if (name.equals(names.elementAt(i))) {
942
return (IDs.elementAt(i)).longValue();
943
}
944
}
945
throw new Failure("Method \"" + name + "\" not found for classID: " + classID);
946
}
947
948
// --------------------------------------------------- //
949
950
/**
951
* Get list of IDs of static fields of given class.
952
*/
953
public long[] getClassFieldIDs(long classID, boolean declared) {
954
Vector<Long> list = new Vector<Long>();
955
addFields(classID, list, null, null, null, false, declared);
956
return makeListOfLongValues(list);
957
}
958
959
/**
960
* Get list of names of static fields of given class.
961
*/
962
public String[] getClassFieldNames(long classID, boolean declared) {
963
Vector<String> list = new Vector<String>();
964
addFields(classID, null, list, null, null, false, declared);
965
return makeListOfStringValues(list);
966
}
967
968
/**
969
* Get list of signatures of static fields of given class.
970
*/
971
public String[] getClassFieldSignatures(long classID, boolean declared) {
972
Vector<String> list = new Vector<String>();
973
addFields(classID, null, null, list, null, false, declared);
974
return makeListOfStringValues(list);
975
}
976
977
/**
978
* Get ID of a static field of given class by name.
979
*/
980
public long getClassFieldID(long classID, String name, boolean declared) {
981
Vector<Long> IDs = new Vector<Long>();
982
Vector<String> names = new Vector<String>();
983
addFields(classID, IDs, names, null, null, false, declared);
984
int count = names.size();
985
for (int i = 0; i < count; i++) {
986
if (name.equals((String)names.elementAt(i))) {
987
return ((Long)IDs.elementAt(i)).longValue();
988
}
989
}
990
throw new Failure("Static field \"" + name + "\" not found for classID: " + classID);
991
}
992
993
// --------------------------------------------------- //
994
995
/**
996
* Get value of a static field of given class.
997
*/
998
public JDWP.Value getStaticFieldValue(long typeID, long fieldID) {
999
String commandName = "ReferenceType.GetValues";
1000
CommandPacket command =
1001
new CommandPacket(JDWP.Command.ReferenceType.GetValues);
1002
command.addReferenceTypeID(typeID);
1003
command.addInt(1);
1004
command.addFieldID(fieldID);
1005
1006
ReplyPacket reply = receiveReplyFor(command, commandName);
1007
JDWP.Value value = null;
1008
1009
try {
1010
reply.resetPosition();
1011
1012
int count = reply.getInt();
1013
if (count < 1) {
1014
throw new Failure("No values returned for static fieldID: " + fieldID);
1015
}
1016
value = reply.getValue();
1017
1018
} catch (BoundException e) {
1019
complain("Unable to parse reply packet for " + commandName +" command:\n\t"
1020
+ e.getMessage());
1021
display("Reply packet:\n" + reply);
1022
throw new Failure("Error occured while getting value of static field: " +
1023
+ fieldID);
1024
}
1025
return value;
1026
}
1027
1028
/**
1029
* Get value of particular type from a static field of given class.
1030
*/
1031
public JDWP.Value getStaticFieldValue(long typeID, String fieldName, byte tag) {
1032
long fieldID = getClassFieldID(typeID, fieldName, true);
1033
JDWP.Value value = getStaticFieldValue(typeID, fieldID);
1034
1035
if (value.getTag() != tag) {
1036
complain("unexpedted value tag returned from debuggee: " + value.getTag()
1037
+ " (expected: " + tag + ")");
1038
throw new Failure("Error occured while getting value from static field: "
1039
+ fieldName);
1040
}
1041
return value;
1042
}
1043
1044
/**
1045
* Set value of a static field of given class.
1046
*/
1047
public void setStaticFieldValue(long typeID, long fieldID, JDWP.Value value) {
1048
String commandName = "ClassType.SetValues";
1049
CommandPacket command =
1050
new CommandPacket(JDWP.Command.ClassType.SetValues);
1051
command.addReferenceTypeID(typeID);
1052
command.addInt(1);
1053
command.addFieldID(fieldID);
1054
command.addUntaggedValue(value, value.getTag());
1055
1056
ReplyPacket reply = receiveReplyFor(command, commandName);
1057
}
1058
1059
/**
1060
* Get value of a field of given object.
1061
*/
1062
public JDWP.Value getObjectFieldValue(long objectID, long fieldID) {
1063
String commandName = "ObjectReference.GetValues";
1064
CommandPacket command =
1065
new CommandPacket(JDWP.Command.ObjectReference.GetValues);
1066
command.addObjectID(objectID);
1067
command.addInt(1);
1068
command.addFieldID(fieldID);
1069
1070
ReplyPacket reply = receiveReplyFor(command, commandName);
1071
JDWP.Value value = null;
1072
1073
try {
1074
reply.resetPosition();
1075
1076
int count = reply.getInt();
1077
if (count < 1) {
1078
throw new Failure("No values returned for object fieldID: " + fieldID);
1079
}
1080
value = reply.getValue();
1081
1082
} catch (BoundException e) {
1083
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1084
+ e.getMessage());
1085
display("Reply packet:\n" + reply);
1086
throw new Failure("Error occured while getting value of object field: " +
1087
+ fieldID);
1088
}
1089
return value;
1090
}
1091
1092
/**
1093
* Set value of a static field of given class.
1094
*/
1095
public void setObjectFieldValue(long objectID, long fieldID, JDWP.Value value) {
1096
String commandName = "ObjectReference.SetValues";
1097
CommandPacket command =
1098
new CommandPacket(JDWP.Command.ObjectReference.SetValues);
1099
command.addObjectID(objectID);
1100
command.addInt(1);
1101
command.addFieldID(fieldID);
1102
command.addUntaggedValue(value, value.getTag());
1103
1104
ReplyPacket reply = receiveReplyFor(command, commandName);
1105
}
1106
1107
// --------------------------------------------------- //
1108
1109
/**
1110
* Find threadID for given thread name among all active threads.
1111
*/
1112
public long getThreadID(String name) {
1113
// request list of all threadIDs
1114
int threads = 0;
1115
long threadIDs[] = null;
1116
{
1117
String commandName = "VirtualMachine.AllThreads";
1118
CommandPacket command = new CommandPacket(JDWP.Command.VirtualMachine.AllThreads);
1119
ReplyPacket reply = receiveReplyFor(command, commandName);
1120
reply.resetPosition();
1121
try {
1122
threads = reply.getInt();
1123
threadIDs = new long[threads];
1124
1125
for (int i = 0; i < threads; i++) {
1126
threadIDs[i] = reply.getObjectID();
1127
}
1128
} catch (BoundException e) {
1129
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1130
+ e.getMessage());
1131
display("Reply packet:\n" + reply);
1132
throw new Failure("Error occured while getting threadID for thread name: "
1133
+ name);
1134
}
1135
}
1136
1137
// request name for each threadID
1138
for (int i = 0; i < threads; i++) {
1139
String commandName = "ThreadReference.Name";
1140
CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Name);
1141
command.addObjectID(threadIDs[i]);
1142
ReplyPacket reply = receiveReplyFor(command, commandName);
1143
try {
1144
reply.resetPosition();
1145
String threadName = reply.getString();
1146
if (threadName.equals(name)) {
1147
return threadIDs[i];
1148
}
1149
} catch (BoundException e) {
1150
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1151
+ e.getMessage());
1152
display("Reply packet:\n" + reply);
1153
throw new Failure("Error occured while getting name for threadID: "
1154
+ threadIDs[i]);
1155
}
1156
}
1157
1158
throw new Failure("No threadID found for thread name: " + name);
1159
}
1160
1161
/**
1162
* Return thread name for the given threadID.
1163
*/
1164
public String getThreadName(long threadID) {
1165
String commandName = "ThreadReference.Name";
1166
CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Name);
1167
command.addObjectID(threadID);
1168
ReplyPacket reply = receiveReplyFor(command, commandName);
1169
try {
1170
reply.resetPosition();
1171
String threadName = reply.getString();
1172
return threadName;
1173
} catch (BoundException e) {
1174
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1175
+ e.getMessage());
1176
display("Reply packet:\n" + reply);
1177
throw new Failure("Error occured while getting name for threadID: "
1178
+ threadID);
1179
}
1180
}
1181
1182
/**
1183
* Suspend thread for the given threadID.
1184
*/
1185
public void suspendThread(long threadID) {
1186
String commandName = "ThreadReference.Suspend";
1187
CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Suspend);
1188
command.addObjectID(threadID);
1189
1190
ReplyPacket reply = receiveReplyFor(command, commandName);
1191
}
1192
1193
/**
1194
* Resume thread for the given threadID.
1195
*/
1196
public void resumeThread(long threadID) {
1197
String commandName = "ThreadReference.resume";
1198
CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Resume);
1199
command.addObjectID(threadID);
1200
1201
ReplyPacket reply = receiveReplyFor(command, commandName);
1202
}
1203
1204
/**
1205
* Return frameID for the current frame of the thread.
1206
* Thread must be suspended.
1207
*/
1208
public long getCurrentFrameID(long threadID) {
1209
String commandName = "ThreadReference.Frames";
1210
CommandPacket command = new CommandPacket(JDWP.Command.ThreadReference.Frames);
1211
command.addObjectID(threadID); // threadID
1212
command.addInt(0); // startFrame
1213
command.addInt(1); // length
1214
1215
ReplyPacket reply = receiveReplyFor(command, commandName);
1216
try {
1217
reply.resetPosition();
1218
int frames = reply.getInt();
1219
if (frames != 1) {
1220
throw new Failure("Not only one current frame returned for threadID "
1221
+ threadID + ": " + frames);
1222
}
1223
long frameID = reply.getFrameID();
1224
JDWP.Location location = reply.getLocation();
1225
return frameID;
1226
} catch (BoundException e) {
1227
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1228
+ e.getMessage());
1229
display("Reply packet:\n" + reply);
1230
throw new Failure("Error occured while getting current frame for threadID: "
1231
+ threadID);
1232
}
1233
}
1234
1235
// --------------------------------------------------- //
1236
1237
/**
1238
* Find line number for the given location from the method line table.
1239
* If <code>approximate</code> is <it>true</i> the found line should begin
1240
* with code index of the given location. Otherwise, the found line will
1241
* just cover code index of the given location.
1242
*/
1243
public int getLineNumber(JDWP.Location location, boolean approximate) {
1244
String commandName = "Method.LineTable";
1245
CommandPacket command = new CommandPacket(JDWP.Command.Method.LineTable);
1246
command.addReferenceTypeID(location.getClassID());
1247
command.addMethodID(location.getMethodID());
1248
long index = location.getIndex();
1249
ReplyPacket reply = receiveReplyFor(command, commandName);
1250
String msg = "Error occured while getting line number for location: " + location;
1251
try {
1252
reply.resetPosition();
1253
long start = reply.getLong();
1254
if (index < start) {
1255
complain("Location index (" + index
1256
+ ") is less than start method index (" + start);
1257
throw new Failure(msg);
1258
}
1259
long end = reply.getLong();
1260
if (index > end) {
1261
complain("Location index (" + index
1262
+ ") is greater than end method index (" + end);
1263
throw new Failure(msg);
1264
}
1265
int lines = reply.getInt();
1266
if (!approximate) {
1267
for (int i = 0; i < lines; i++) {
1268
long lineCodeIndex = reply.getLong();
1269
int lineNumber = reply.getInt();
1270
if (lineCodeIndex == index) {
1271
return lineNumber;
1272
}
1273
}
1274
throw new Failure("No exact line number exactly for location: " + location);
1275
} else {
1276
int prevLine = -1;
1277
for (int i = 0; i < lines; i++) {
1278
long lineCodeIndex = reply.getLong();
1279
int lineNumber = reply.getInt();
1280
if (lineCodeIndex == index) {
1281
return lineNumber;
1282
} else if (lineCodeIndex > index) {
1283
break;
1284
}
1285
prevLine = lineNumber;
1286
}
1287
if (prevLine < 0)
1288
throw new Failure("No approximate line number found for location: " + location);
1289
return prevLine;
1290
}
1291
} catch (BoundException e) {
1292
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1293
+ e.getMessage());
1294
display("Reply packet:\n" + reply);
1295
throw new Failure(msg);
1296
}
1297
}
1298
1299
/**
1300
* Find line index for the given line number from the method line table.
1301
*/
1302
public long getCodeIndex(long classID, long methodID, int lineNumber) {
1303
String commandName = "Method.LineTable";
1304
CommandPacket command = new CommandPacket(JDWP.Command.Method.LineTable);
1305
command.addReferenceTypeID(classID);
1306
command.addMethodID(methodID);
1307
ReplyPacket reply = receiveReplyFor(command, commandName);
1308
String msg = "Error occured while getting code index for line number: " + lineNumber;
1309
try {
1310
reply.resetPosition();
1311
long start = reply.getLong();
1312
long end = reply.getLong();
1313
int lines = reply.getInt();
1314
for (int i = 0; i < lines; i++) {
1315
long lineCodeIndex = reply.getLong();
1316
int line = reply.getInt();
1317
if (lineNumber == line) {
1318
return lineCodeIndex;
1319
}
1320
}
1321
} catch (BoundException e) {
1322
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1323
+ e.getMessage());
1324
display("Reply packet:\n" + reply);
1325
throw new Failure(msg);
1326
}
1327
1328
throw new Failure("No code index found for line number: " + lineNumber);
1329
}
1330
1331
// --------------------------------------------------- //
1332
1333
/**
1334
* Make the specified event request into debuggee.
1335
*/
1336
public int requestEvent(CommandPacket requestCommand, String name) {
1337
String commandName = "EventRequest.Set";
1338
ReplyPacket reply = receiveReplyFor(requestCommand, name);
1339
1340
try {
1341
reply.resetPosition();
1342
1343
int requestID = reply.getInt();
1344
return requestID;
1345
1346
} catch (BoundException e) {
1347
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1348
+ e.getMessage());
1349
display("Request command packet:\n" + requestCommand);
1350
display("Reply packet:\n" + reply);
1351
throw new Failure("Error occured while making event request: " + name);
1352
}
1353
}
1354
1355
/**
1356
* Remove existing event request from debuggee.
1357
*/
1358
public void clearEventRequest(byte eventKind, int requestID) {
1359
String commandName = "EventRequest.Clear";
1360
CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear);
1361
command.addByte(eventKind);
1362
command.addInt(requestID);
1363
ReplyPacket reply = receiveReplyFor(command, commandName);
1364
}
1365
1366
/**
1367
* Make request for CLASS_PREPARE event for specified class into debuggee.
1368
*/
1369
public int requestClassPrepareEvent(String className, byte suspendPolicy) {
1370
CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set);
1371
command.addByte(JDWP.EventKind.CLASS_PREPARE);
1372
command.addByte(suspendPolicy);
1373
command.addInt(1);
1374
command.addByte(JDWP.EventModifierKind.CLASS_MATCH);
1375
command.addString(className);
1376
1377
return requestEvent(command, "CLASS_PREPARE");
1378
}
1379
1380
/**
1381
* Make request for BREAKPOINT event for the specified location into debuggee.
1382
*/
1383
public int requestBreakpointEvent(JDWP.Location location, byte suspendPolicy) {
1384
CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set);
1385
command.addByte(JDWP.EventKind.BREAKPOINT);
1386
command.addByte(suspendPolicy);
1387
command.addInt(1);
1388
command.addByte(JDWP.EventModifierKind.LOCATION_ONLY);
1389
command.addLocation(location);
1390
return requestEvent(command, "BREAKPOINT");
1391
}
1392
1393
/**
1394
* Make request for BREAKPOINT event for the specified line of the given method.
1395
*/
1396
public int requestBreakpointEvent(byte typeTag, long classID, long methodID,
1397
int lineNumber, byte suspendPolicy) {
1398
long codeIndex = getCodeIndex(classID, methodID, lineNumber);
1399
JDWP.Location location = new JDWP.Location(typeTag, classID, methodID, codeIndex);
1400
return requestBreakpointEvent(location, suspendPolicy);
1401
}
1402
1403
/**
1404
* Remove all existing BREAKPOINT event requests from debuggee.
1405
*/
1406
public void clearAllBreakpoints() {
1407
String commandName = "EventRequest.ClearAllBreakpoints";
1408
CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.ClearAllBreakpoints);
1409
ReplyPacket reply = receiveReplyFor(command, commandName);
1410
}
1411
1412
// --------------------------------------------------- //
1413
1414
/**
1415
* Add IDs of supertypes (interfaces and classes) for given class to the lists.
1416
*/
1417
private void addSupertypes(long referenceTypeID, Vector<Long> supertypes,
1418
Vector<Long> interfaces, Vector<Long> superclasses,
1419
boolean interfaceOnly, boolean declared) {
1420
1421
if (supertypes != null || interfaces != null) {
1422
1423
// obtain list of direct implemented interfaces
1424
String commandName = "ReferenceType.Interfaces";
1425
CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Interfaces);
1426
command.addReferenceTypeID(referenceTypeID);
1427
ReplyPacket reply = receiveReplyFor(command, commandName);
1428
1429
try {
1430
reply.resetPosition();
1431
1432
int count = reply.getInt();
1433
if (count < 0) {
1434
throw new Failure("Negative number (" + count
1435
+ ") of declared interfaces received for referenceTypeID: "
1436
+ referenceTypeID);
1437
}
1438
1439
for (int i = 0; i < count; i++) {
1440
long typeID = reply.getReferenceTypeID();
1441
if (!declared) {
1442
addSupertypes(typeID, supertypes, interfaces, superclasses,
1443
true, declared);
1444
}
1445
Long value = Long.valueOf(typeID);
1446
if (supertypes != null) {
1447
supertypes.add(value);
1448
}
1449
if (interfaces != null) {
1450
interfaces.add(value);
1451
}
1452
}
1453
1454
} catch (BoundException e) {
1455
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1456
+ e.getMessage());
1457
display("Reply packet:\n" + reply);
1458
throw new Failure("Error occured while getting interfeceIDs for referenceTypeID: " +
1459
+ referenceTypeID);
1460
}
1461
1462
}
1463
1464
if (!interfaceOnly) {
1465
1466
String commandName = "ClassType.Superclasses";
1467
CommandPacket command = new CommandPacket(JDWP.Command.ClassType.Superclass);
1468
command.addReferenceTypeID(referenceTypeID);
1469
ReplyPacket reply = receiveReplyFor(command, commandName);
1470
1471
try {
1472
reply.resetPosition();
1473
1474
long typeID = reply.getReferenceTypeID();
1475
if (typeID != 0) {
1476
if (!declared) {
1477
addSupertypes(typeID, supertypes, interfaces, superclasses,
1478
false, declared);
1479
}
1480
Long value = Long.valueOf(typeID);
1481
if (supertypes != null) {
1482
supertypes.add(value);
1483
}
1484
if (superclasses != null) {
1485
superclasses.add(value);
1486
}
1487
}
1488
} catch (BoundException e) {
1489
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1490
+ e.getMessage());
1491
display("Reply packet:\n" + reply);
1492
throw new Failure("Error occured while getting superclass ID for classID: " +
1493
+ referenceTypeID);
1494
}
1495
1496
}
1497
}
1498
1499
/**
1500
* Add attributes of fields of given class to the lists.
1501
*/
1502
private void addFields(long referenceTypeID, Vector<Long> IDs, Vector<String> names,
1503
Vector<String> signatures, Vector<Integer> modifiers,
1504
boolean interfaceOnly, boolean declared) {
1505
1506
if (!declared) {
1507
Vector<Long> supertypes = new Vector<Long>();
1508
addSupertypes(referenceTypeID, supertypes, null, null, interfaceOnly, declared);
1509
int count = supertypes.size();
1510
for (int i = 0; i < count; i++) {
1511
long typeID = (supertypes.elementAt(i)).longValue();
1512
addFields(typeID, IDs, names, signatures, modifiers,
1513
interfaceOnly, declared);
1514
}
1515
}
1516
1517
String commandName = "ReferenceType.Fields";
1518
CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Fields);
1519
command.addReferenceTypeID(referenceTypeID);
1520
ReplyPacket reply = receiveReplyFor(command, commandName);
1521
1522
try {
1523
reply.resetPosition();
1524
1525
int count = reply.getInt();
1526
if (count < 0) {
1527
throw new Failure("Negative number (" + count
1528
+ ") of declared fields received for referenceTypeID: "
1529
+ referenceTypeID);
1530
}
1531
1532
for (int i = 0; i < count; i++) {
1533
long id = reply.getFieldID();
1534
String name = reply.getString();
1535
String signature = reply.getString();
1536
int modBits = reply.getInt();
1537
1538
if (IDs != null)
1539
IDs.add(Long.valueOf(id));
1540
if (names != null)
1541
names.add(name);
1542
if (signatures != null)
1543
signatures.add(signature);
1544
if (modifiers != null)
1545
modifiers.add(Integer.valueOf(modBits));
1546
}
1547
1548
} catch (BoundException e) {
1549
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1550
+ e.getMessage());
1551
display("Reply packet:\n" + reply);
1552
throw new Failure("Error occured while getting fieldIDs for referenceTypeID: " +
1553
+ referenceTypeID);
1554
}
1555
}
1556
1557
/**
1558
* Add attributes of methods of given class to the lists.
1559
*/
1560
private void addMethods(long referenceTypeID, Vector<Long> IDs, Vector<String> names,
1561
Vector<String> signatures, Vector<Integer> modifiers,
1562
boolean interfaceOnly, boolean declared) {
1563
1564
if (!declared) {
1565
Vector<Long> supertypes = new Vector<Long>();
1566
addSupertypes(referenceTypeID, supertypes, null, null, interfaceOnly, declared);
1567
int count = supertypes.size();
1568
for (int i = 0; i < count; i++) {
1569
long typeID = (supertypes.elementAt(i)).longValue();
1570
addMethods(typeID, IDs, names, signatures, modifiers,
1571
interfaceOnly, declared);
1572
}
1573
}
1574
1575
String commandName = "ReferenceType.Methods";
1576
CommandPacket command = new CommandPacket(JDWP.Command.ReferenceType.Methods);
1577
command.addReferenceTypeID(referenceTypeID);
1578
ReplyPacket reply = receiveReplyFor(command, commandName);
1579
1580
try {
1581
reply.resetPosition();
1582
1583
int count = reply.getInt();
1584
if (count < 0) {
1585
throw new Failure("Negative number (" + count
1586
+ ") of declared fields received for referenceTypeID: "
1587
+ referenceTypeID);
1588
}
1589
1590
for (int i = 0; i < count; i++) {
1591
long id = reply.getMethodID();
1592
String name = reply.getString();
1593
String signature = reply.getString();
1594
int modBits = reply.getInt();
1595
1596
if (IDs != null)
1597
IDs.add(Long.valueOf(id));
1598
if (names != null)
1599
names.add(name);
1600
if (signatures != null)
1601
signatures.add(signature);
1602
if (modifiers != null)
1603
modifiers.add(Integer.valueOf(modBits));
1604
}
1605
1606
} catch (BoundException e) {
1607
complain("Unable to parse reply packet for " + commandName + " command:\n\t"
1608
+ e.getMessage());
1609
display("Reply packet:\n" + reply);
1610
throw new Failure("Error occured while getting methodIDs for referenceTypeID: " +
1611
+ referenceTypeID);
1612
}
1613
}
1614
1615
// --------------------------------------------------- //
1616
1617
private static long[] makeListOfLongValues(Vector<Long> vector) {
1618
int count = vector.size();
1619
long[] list = new long[count];
1620
for (int i = 0; i < count; i++) {
1621
list[i] = (vector.elementAt(i)).longValue();
1622
}
1623
return list;
1624
}
1625
1626
private static String[] makeListOfStringValues(Vector<String> vector) {
1627
int count = vector.size();
1628
String[] list = new String[count];
1629
for (int i = 0; i < count; i++) {
1630
list[i] = vector.elementAt(i);
1631
}
1632
return list;
1633
}
1634
1635
// --------------------------------------------------- //
1636
1637
/**
1638
* Force debugge VM to exit using JDWP connection if possible.
1639
*/
1640
protected void killDebugee() {
1641
// ignore
1642
}
1643
1644
/**
1645
* Close transport channel and kill the debugee VM if it is not terminated yet.
1646
*/
1647
public void close() {
1648
if (transport != null) {
1649
try {
1650
transport.close();
1651
} catch (IOException e) {
1652
log.display("WARNING: Caught IOException while closing JDWP connection:\n\t"
1653
+ e);
1654
}
1655
}
1656
super.close();
1657
}
1658
1659
}
1660
1661