Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Binder.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.jdi;
25
26
import jdk.test.lib.Platform;
27
import nsk.share.*;
28
import nsk.share.jpda.*;
29
30
import com.sun.jdi.*;
31
import com.sun.jdi.connect.*;
32
33
import com.sun.jdi.connect.Connector.Argument;
34
import java.io.*;
35
import java.net.*;
36
import java.util.*;
37
38
/**
39
* This class provides debugger with connection to debugee VM
40
* using JDI connectors.
41
*<p>
42
* This class provides abilities to launch and bind to debugee VM
43
* as described for base <code>DebugeeBinder</code> class,
44
* using JDI connectors and <code>com.sun.VirtualMachine</code> mirror.
45
* <p>
46
* When <code>Binder</code> is asked to bind to debugee by invoking
47
* <code>bindToBebugee()</code> method it uses
48
* <code>com.sun.jdi.Connector</code> object corresponding to
49
* value of command line options <code>-connector</code> and
50
* <code>-transport</code> to launch and connect to debugee VM.
51
* After debugee is launched and connection is established
52
* <code>Binder</code> uses <code>com.sun.jdi.VirtualMachine</code>
53
* object to construct <code>Debugee</code> object, that
54
* provides abilities to interact with debugee VM.
55
*
56
* @see Debugee
57
* @see DebugeeBinder
58
*/
59
public class Binder extends DebugeeBinder {
60
61
/**
62
* Default message prefix for <code>Binder</code> object.
63
*/
64
public static final String LOG_PREFIX = "binder> ";
65
66
/**
67
* Get version string.
68
*/
69
public static String getVersion () {
70
return "@(#)Binder.java 1.14 03/10/08";
71
}
72
73
// -------------------------------------------------- //
74
75
/**
76
* Handler of command line arguments.
77
*/
78
private ArgumentHandler argumentHandler = null;
79
80
/**
81
* Return <code>argumentHandler</code> of this binder.
82
*/
83
public ArgumentHandler getArgumentHandler() {
84
return argumentHandler;
85
}
86
87
// -------------------------------------------------- //
88
89
/**
90
* Make <code>Binder</code> object and pass raw command line arguments.
91
*
92
* @deprecated Use newer
93
* <code>Binder(ArgumentHandler,Log)</code>
94
* constructor.
95
*/
96
@Deprecated
97
public Binder (String args[]) {
98
this(args, new Log(System.err));
99
}
100
101
/**
102
* Make <code>Binder</code> object for raw command line arguments
103
* and specified <code>log</code> object.
104
*
105
* @deprecated Use newer
106
* <code>Binder(ArgumentHandler,Log)</code>
107
* constructor.
108
*/
109
@Deprecated
110
public Binder (String args[], Log log) {
111
this(new ArgumentHandler(args), log);
112
}
113
114
/**
115
* Make <code>Binder</code> object for specified command line arguments
116
* and <code>log</code> object.
117
*/
118
public Binder (ArgumentHandler argumentHandler, Log log) {
119
super(argumentHandler, log);
120
this.argumentHandler = argumentHandler;
121
}
122
123
// -------------------------------------------------- //
124
125
/**
126
* Make initial <code>Debugee</code> object for local debuggee process
127
* started with launching connector.
128
*/
129
public Debugee makeLocalDebugee(Process process) {
130
LocalLaunchedDebugee debugee = new LocalLaunchedDebugee(process, this);
131
132
Finalizer finalizer = new Finalizer(debugee);
133
finalizer.activate();
134
135
return debugee;
136
}
137
138
/**
139
* Launch local debuggee process with specified command line
140
* and make initial <code>Debugee</code> object.
141
*/
142
public Debugee startLocalDebugee(String cmd) {
143
Process process = null;
144
145
try {
146
process = launchProcess(cmd);
147
} catch (IOException e) {
148
e.printStackTrace(log.getOutStream());
149
throw new Failure("Caught exception while launching local debuggee VM process:\n\t"
150
+ e);
151
}
152
153
return makeLocalDebugee(process);
154
}
155
156
/**
157
* Make debuggee wrapper for already launched debuggee VM.
158
* After enwraping debugee's output is redirected to Binder's log,
159
* VMStartEvent is received and debuggee is initialized.
160
*/
161
public Debugee enwrapDebugee(VirtualMachine vm, Process proc) {
162
Debugee debugee = makeLocalDebugee(proc);
163
164
display("Redirecting VM output");
165
debugee.redirectOutput(log);
166
debugee.setupVM(vm);
167
168
long timeout = argumentHandler.getWaitTime() * 60 * 1000; // milliseconds
169
170
display("Waiting for VM initialized");
171
debugee.waitForVMInit(timeout);
172
173
return debugee;
174
}
175
176
/**
177
* Launch debugee VM and establish connection to it without waiting for VMStartEvent.
178
* After launching debugee's output is redirected to Binder's log,
179
* but VMStartEvent is not received and so debuggee is not fully initialized.
180
*
181
* @see #bindToDebugee(String)
182
*/
183
public Debugee bindToDebugeeNoWait(String classToExecute) {
184
185
VirtualMachineManager vmm = Bootstrap.virtualMachineManager();
186
display("VirtualMachineManager: version "
187
+ vmm.majorInterfaceVersion() + "."
188
+ vmm.minorInterfaceVersion());
189
190
Debugee debugee = null;
191
192
String classPath = null;
193
// classPath = System.getProperty("java.class.path");
194
195
prepareForPipeConnection(argumentHandler);
196
197
if (argumentHandler.isLaunchedLocally()) {
198
199
if (argumentHandler.isDefaultConnector()) {
200
debugee = localDefaultLaunchDebugee(vmm, classToExecute, classPath);
201
} else if (argumentHandler.isRawLaunchingConnector()) {
202
debugee = localRawLaunchDebugee(vmm, classToExecute, classPath);
203
} else if (argumentHandler.isLaunchingConnector()) {
204
debugee = localLaunchDebugee(vmm, classToExecute, classPath);
205
} else if (argumentHandler.isAttachingConnector()) {
206
debugee = localLaunchAndAttachDebugee(vmm, classToExecute, classPath);
207
} else if (argumentHandler.isListeningConnector()) {
208
debugee = localLaunchAndListenDebugee(vmm, classToExecute, classPath);
209
} else {
210
throw new TestBug("Unexpected connector type for local debugee launch mode"
211
+ argumentHandler.getConnectorType());
212
}
213
214
} else if (argumentHandler.isLaunchedRemotely()) {
215
216
connectToBindServer(classToExecute);
217
218
if (argumentHandler.isAttachingConnector()) {
219
debugee = remoteLaunchAndAttachDebugee(vmm, classToExecute, classPath);
220
} else if (argumentHandler.isListeningConnector()) {
221
debugee = remoteLaunchAndListenDebugee(vmm, classToExecute, classPath);
222
} else {
223
throw new TestBug("Unexpected connector type for remote debugee launch mode"
224
+ argumentHandler.getConnectorType());
225
}
226
227
} else if (argumentHandler.isLaunchedManually()) {
228
229
if (argumentHandler.isAttachingConnector()) {
230
debugee = manualLaunchAndAttachDebugee(vmm, classToExecute, classPath);
231
} else if (argumentHandler.isListeningConnector()) {
232
debugee = manualLaunchAndListenDebugee(vmm, classToExecute, classPath);
233
} else {
234
throw new TestBug("Unexpected connector type for manual debugee launch mode"
235
+ argumentHandler.getConnectorType());
236
}
237
238
} else {
239
throw new Failure("Unexpected debugee launching mode: " + argumentHandler.getLaunchMode());
240
}
241
242
return debugee;
243
}
244
245
/**
246
* Launch debugee VM and establish JDI connection.
247
* After launching debugee's output is redirected to Binder's log,
248
* VMStart event is received and debuggee is initialized.
249
*
250
* @see #bindToDebugeeNoWait(String)
251
*/
252
public Debugee bindToDebugee(String classToExecute) {
253
Debugee debugee = bindToDebugeeNoWait(classToExecute);
254
255
if(argumentHandler.getOptions().getProperty("traceAll") != null)
256
debugee.VM().setDebugTraceMode(VirtualMachine.TRACE_ALL);
257
258
long timeout = argumentHandler.getWaitTime() * 60 * 1000; // milliseconds
259
260
display("Waiting for VM initialized");
261
debugee.waitForVMInit(timeout);
262
263
return debugee;
264
}
265
266
// -------------------------------------------------- //
267
268
/**
269
* Launch debugee locally via the default LaunchingConnector.
270
*/
271
private Debugee localDefaultLaunchDebugee (VirtualMachineManager vmm,
272
String classToExecute,
273
String classPath) {
274
display("Finding connector: " + "default" );
275
LaunchingConnector connector = vmm.defaultConnector();
276
Map<String,? extends Argument> arguments = setupLaunchingConnector(connector, classToExecute, classPath);
277
278
VirtualMachine vm;
279
try {
280
display("Launching debugee");
281
vm = connector.launch(arguments);
282
} catch (IllegalConnectorArgumentsException e) {
283
e.printStackTrace(log.getOutStream());
284
throw new TestBug("Wrong connector arguments used to launch debuggee VM:\n\t" + e);
285
} catch (VMStartException e) {
286
e.printStackTrace(log.getOutStream());
287
String msg = readVMStartExceptionOutput(e, log.getOutStream());
288
throw new Failure("Caught exception while starting debugee VM:\n\t" + e + "\n" + msg);
289
} catch (IOException e) {
290
e.printStackTrace(log.getOutStream());
291
throw new Failure("Caught exception while launching debugee VM:\n\t" + e);
292
};
293
294
Process process = vm.process();
295
Debugee debugee = makeLocalDebugee(process);
296
debugee.redirectOutput(log);
297
debugee.setupVM(vm);
298
299
return debugee;
300
}
301
302
303
/**
304
* Launch debugee locally via the default LaunchingConnector.
305
*/
306
private Debugee localLaunchDebugee (VirtualMachineManager vmm,
307
String classToExecute,
308
String classPath) {
309
310
display("Finding connector: " + argumentHandler.getConnectorName() );
311
LaunchingConnector connector =
312
(LaunchingConnector) findConnector(argumentHandler.getConnectorName(),
313
vmm.launchingConnectors());
314
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupLaunchingConnector(connector, classToExecute, classPath);
315
316
VirtualMachine vm;
317
try {
318
display("Launching debugee");
319
vm = connector.launch(arguments);
320
} catch (IllegalConnectorArgumentsException e) {
321
e.printStackTrace(log.getOutStream());
322
throw new TestBug("Wrong connector arguments used to launch debuggee VM:\n\t" + e);
323
} catch (VMStartException e) {
324
e.printStackTrace(log.getOutStream());
325
String msg = readVMStartExceptionOutput(e, log.getOutStream());
326
throw new Failure("Caught exception while starting debugee VM:\n\t" + e + "\nProcess output:\n\t" + msg);
327
} catch (IOException e) {
328
e.printStackTrace(log.getOutStream());
329
throw new Failure("Caught exception while launching debugee VM:\n\t" + e);
330
};
331
332
Process process = vm.process();
333
Debugee debugee = makeLocalDebugee(process);
334
debugee.redirectOutput(log);
335
debugee.setupVM(vm);
336
337
return debugee;
338
}
339
340
/**
341
* Launch debugee locally via the RawLaunchingConnector.
342
*/
343
private Debugee localRawLaunchDebugee (VirtualMachineManager vmm,
344
String classToExecute,
345
String classPath) {
346
display("Finding connector: " + argumentHandler.getConnectorName() );
347
LaunchingConnector connector =
348
(LaunchingConnector) findConnector(argumentHandler.getConnectorName(),
349
vmm.launchingConnectors());
350
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupRawLaunchingConnector(connector, classToExecute, classPath);
351
352
VirtualMachine vm;
353
try {
354
display("Launching debugee");
355
vm = connector.launch(arguments);
356
} catch (IllegalConnectorArgumentsException e) {
357
e.printStackTrace(log.getOutStream());
358
throw new TestBug("Wrong connector arguments used to launch debuggee VM:\n\t" + e);
359
} catch (VMStartException e) {
360
e.printStackTrace(log.getOutStream());
361
String msg = readVMStartExceptionOutput(e, log.getOutStream());
362
throw new Failure("Caught exception while starting debugee VM:\n\t" + e + "\nProcess output:\n\t" + msg);
363
} catch (IOException e) {
364
e.printStackTrace(log.getOutStream());
365
throw new Failure("Caught exception while launching debugee VM:\n\t" + e);
366
};
367
368
Process process = vm.process();
369
Debugee debugee = makeLocalDebugee(process);
370
debugee.redirectOutput(log);
371
debugee.setupVM(vm);
372
373
return debugee;
374
}
375
376
/**
377
* Launch debugee VM locally as a local process and connect to it using
378
* <code>AttachingConnector</code>.
379
*/
380
private Debugee localLaunchAndAttachDebugee (VirtualMachineManager vmm,
381
String classToExecute,
382
String classPath) {
383
display("FindingConnector: " + argumentHandler.getConnectorName() );
384
AttachingConnector connector =
385
(AttachingConnector) findConnector(argumentHandler.getConnectorName(),
386
vmm.attachingConnectors());
387
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupAttachingConnector(connector, classToExecute, classPath);
388
389
String address = makeTransportAddress();
390
String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
391
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
392
393
display("Starting java process:\n\t" + javaCmdLine);
394
Debugee debugee = startLocalDebugee(cmdLineArgs);
395
debugee.redirectOutput(log);
396
397
display("Attaching to debugee");
398
VirtualMachine vm = null;
399
IOException ioe = null;
400
for (int i = 0; i < CONNECT_TRIES; i++) {
401
try {
402
vm = connector.attach(arguments);
403
display("Debugee attached");
404
debugee.setupVM(vm);
405
return debugee;
406
} catch (IOException e) {
407
display("Attempt #" + i + " to connect to debugee VM failed:\n\t" + e);
408
ioe = e;
409
if (debugee.terminated()) {
410
throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
411
}
412
try {
413
Thread.currentThread().sleep(CONNECT_TRY_DELAY);
414
} catch (InterruptedException ie) {
415
ie.printStackTrace(log.getOutStream());
416
throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
417
+ ie);
418
}
419
} catch (IllegalConnectorArgumentsException e) {
420
e.printStackTrace(log.getOutStream());
421
throw new TestBug("Wrong connector arguments used to attach to debuggee VM:\n\t" + e);
422
}
423
}
424
throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
425
+ " tries:\n\t" + ioe);
426
}
427
428
/**
429
* Launch debugee VM locally as a local process and connect to it using
430
* <code>ListeningConnector</code>.
431
*/
432
private Debugee localLaunchAndListenDebugee (VirtualMachineManager vmm,
433
String classToExecute,
434
String classPath) {
435
display("Finding connector: " + argumentHandler.getConnectorName() );
436
ListeningConnector connector =
437
(ListeningConnector) findConnector(argumentHandler.getConnectorName(),
438
vmm.listeningConnectors());
439
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupListeningConnector(connector, classToExecute, classPath);
440
441
String address = null;
442
try {
443
display("Listening for connection from debugee");
444
address = connector.startListening(arguments);
445
} catch (IllegalConnectorArgumentsException e) {
446
e.printStackTrace(log.getOutStream());
447
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
448
} catch (IOException e) {
449
e.printStackTrace(log.getOutStream());
450
throw new Failure("Caught exception while starting listening debugee VM:\n\t" + e);
451
};
452
453
String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
454
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
455
456
display("Starting java process:\n\t" + javaCmdLine);
457
Debugee debugee = startLocalDebugee(cmdLineArgs);
458
debugee.redirectOutput(log);
459
460
display("Waiting for connection from debugee");
461
VirtualMachine vm = null;
462
IOException ioe = null;
463
for (int i = 0; i < CONNECT_TRIES; i++) {
464
try {
465
vm = connector.accept(arguments);
466
connector.stopListening(arguments);
467
display("Debugee attached");
468
debugee.setupVM(vm);
469
return debugee;
470
} catch (IOException e) {
471
display("Attempt #" + i + " to listen debugee VM failed:\n\t" + e);
472
ioe = e;
473
if (debugee.terminated()) {
474
throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
475
}
476
try {
477
Thread.currentThread().sleep(CONNECT_TRY_DELAY);
478
} catch (InterruptedException ie) {
479
ie.printStackTrace(log.getOutStream());
480
throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
481
+ ie);
482
}
483
} catch (IllegalConnectorArgumentsException e) {
484
e.printStackTrace(log.getOutStream());
485
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
486
}
487
}
488
throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
489
+ " tries:\n\t" + ioe);
490
}
491
492
// -------------------------------------------------- //
493
494
/**
495
* Launch debugee VM remotely via <code>BindServer</code> and connect to it using
496
* <code>AttachingConnector</code>.
497
*/
498
private Debugee remoteLaunchAndAttachDebugee (VirtualMachineManager vmm,
499
String classToExecute,
500
String classPath) {
501
display("Finding connector: " + argumentHandler.getConnectorName() );
502
AttachingConnector connector =
503
(AttachingConnector) findConnector(argumentHandler.getConnectorName(),
504
vmm.attachingConnectors());
505
506
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupAttachingConnector(connector, classToExecute, classPath);
507
508
String address = makeTransportAddress();
509
String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
510
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
511
512
display("Starting remote java process:\n\t" + javaCmdLine);
513
Debugee debugee = startRemoteDebugee(cmdLineArgs);
514
515
display("Attaching to debugee");
516
VirtualMachine vm;
517
IOException ioe = null;
518
for (int i = 0; i < CONNECT_TRIES; i++) {
519
try {
520
vm = connector.attach(arguments);
521
display("Debugee attached");
522
debugee.setupVM(vm);
523
return debugee;
524
} catch (IOException e) {
525
display("Attempt #" + i + " to connect to debugee VM failed:\n\t" + e);
526
ioe = e;
527
if (debugee.terminated()) {
528
throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
529
}
530
try {
531
Thread.currentThread().sleep(CONNECT_TRY_DELAY);
532
} catch (InterruptedException ie) {
533
ie.printStackTrace(log.getOutStream());
534
throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
535
+ ie);
536
}
537
} catch (IllegalConnectorArgumentsException e) {
538
e.printStackTrace(log.getOutStream());
539
throw new TestBug("Wrong connector arguments used to attach to debuggee VM:\n\t" + e);
540
}
541
}
542
throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
543
+ " tries:\n\t" + ioe);
544
}
545
546
/**
547
* Launch debugee VM remotely via <code>BindServer</code> and connect to it using
548
* <code>ListeningConnector</code>.
549
*/
550
private Debugee remoteLaunchAndListenDebugee (VirtualMachineManager vmm,
551
String classToExecute,
552
String classPath) {
553
display("Finding connector: " + argumentHandler.getConnectorName() );
554
ListeningConnector connector =
555
(ListeningConnector) findConnector(argumentHandler.getConnectorName(),
556
vmm.listeningConnectors());
557
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupListeningConnector(connector, classToExecute, classPath);
558
559
String address = null;
560
try {
561
display("Listening for connection from debugee");
562
address = connector.startListening(arguments);
563
} catch (IllegalConnectorArgumentsException e) {
564
e.printStackTrace(log.getOutStream());
565
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
566
} catch (IOException e) {
567
e.printStackTrace(log.getOutStream());
568
throw new Failure("Caught exception while starting listening debugee VM:\n\t" + e);
569
};
570
571
String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
572
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
573
574
display("Starting remote java process:\n\t" + javaCmdLine);
575
Debugee debugee = startRemoteDebugee(cmdLineArgs);
576
577
display("Waiting for connection from debugee");
578
VirtualMachine vm;
579
IOException ioe = null;
580
for (int i = 0; i < CONNECT_TRIES; i++) {
581
try {
582
vm = connector.accept(arguments);
583
connector.stopListening(arguments);
584
display("Debugee attached");
585
debugee.setupVM(vm);
586
return debugee;
587
} catch (IOException e) {
588
display("Attempt #" + i + " to listen debugee VM failed:\n\t" + e);
589
ioe = e;
590
if (debugee.terminated()) {
591
throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
592
}
593
try {
594
Thread.currentThread().sleep(CONNECT_TRY_DELAY);
595
} catch (InterruptedException ie) {
596
ie.printStackTrace(log.getOutStream());
597
throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
598
+ ie);
599
}
600
} catch (IllegalConnectorArgumentsException e) {
601
e.printStackTrace(log.getOutStream());
602
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
603
}
604
}
605
throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
606
+ " tries:\n\t" + ioe);
607
}
608
609
// -------------------------------------------------- //
610
611
/**
612
* Prompt to manually launch debugee VM and connect to it using
613
* <code>AttachingConnector</code>.
614
*/
615
private Debugee manualLaunchAndAttachDebugee (VirtualMachineManager vmm,
616
String classToExecute,
617
String classPath) {
618
display("Finding connector: " + argumentHandler.getConnectorName() );
619
AttachingConnector connector =
620
(AttachingConnector) findConnector(argumentHandler.getConnectorName(),
621
vmm.attachingConnectors());
622
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupAttachingConnector(connector, classToExecute, classPath);
623
624
String address = makeTransportAddress();
625
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
626
627
display("Starting manual java process:\n\t" + javaCmdLine);
628
ManualLaunchedDebugee debugee = startManualDebugee(javaCmdLine);
629
630
VirtualMachine vm;
631
try {
632
display("Attaching to debugee");
633
vm = connector.attach(arguments);
634
} catch (IllegalConnectorArgumentsException e) {
635
e.printStackTrace(log.getOutStream());
636
throw new TestBug("Wrong connector arguments used to attach to debuggee VM:\n\t" + e);
637
} catch (IOException e) {
638
e.printStackTrace(log.getOutStream());
639
throw new Failure("Caught exception while attaching to debugee VM:\n\t" + e);
640
};
641
display("Debugee attached");
642
643
debugee.setupVM(vm);
644
return debugee;
645
}
646
647
/**
648
* Prompt to manually launch debugee VM and connect to it using
649
* <code>ListeningConnector</code>.
650
*/
651
private Debugee manualLaunchAndListenDebugee (VirtualMachineManager vmm,
652
String classToExecute,
653
String classPath) {
654
display("Finding connector: " + argumentHandler.getConnectorName() );
655
ListeningConnector connector =
656
(ListeningConnector) findConnector(argumentHandler.getConnectorName(),
657
vmm.listeningConnectors());
658
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupListeningConnector(connector, classToExecute, classPath);
659
660
VirtualMachine vm;
661
try {
662
display("Listening for connection from debugee");
663
String address = connector.startListening(arguments);
664
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
665
display("Starting manual java process:\n\t" + javaCmdLine);
666
ManualLaunchedDebugee debugee = startManualDebugee(javaCmdLine);
667
display("Waiting for connection from debugee");
668
vm = connector.accept(arguments);
669
display("Debugee attached");
670
connector.stopListening(arguments);
671
debugee.setupVM(vm);
672
return debugee;
673
} catch (IllegalConnectorArgumentsException e) {
674
e.printStackTrace(log.getOutStream());
675
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
676
} catch (IOException e) {
677
e.printStackTrace(log.getOutStream());
678
throw new Failure("Caught exception while listening to debugee VM:\n\t" + e);
679
}
680
}
681
682
// -------------------------------------------------- //
683
684
/**
685
* Make proper arguments for LaunchingConnector.
686
*/
687
private Map<String,? extends Argument> setupLaunchingConnector(LaunchingConnector connector,
688
String classToExecute,
689
String classPath) {
690
display("LaunchingConnector:");
691
display(" name: " + connector.name());
692
display(" description: " + connector.description());
693
display(" transport: " + connector.transport());
694
695
Hashtable<String,? extends Argument> arguments = new Hashtable<String,Argument>(connector.defaultArguments());
696
697
Connector.Argument arg;
698
699
arg = (Connector.StringArgument) arguments.get("quote");
700
String quote = "\0";
701
arg.setValue(quote);
702
703
String[] rawArgs = argumentHandler.getRawArguments();
704
if (Platform.isWindows()) {
705
// " has to be escaped on windows
706
rawArgs = Arrays.stream(rawArgs)
707
.map(s -> s.replace("\"", "\\\""))
708
.toArray(String[]::new);
709
}
710
711
String cmdline = classToExecute + " " + ArgumentHandler.joinArguments(rawArgs, quote);
712
713
arg = (Connector.StringArgument) arguments.get("main");
714
arg.setValue(cmdline);
715
716
if (! argumentHandler.willDebugeeSuspended()) {
717
Connector.BooleanArgument barg = (Connector.BooleanArgument) arguments.get("suspend");
718
barg.setValue(true);
719
}
720
721
/*
722
if (! argumentHandler.isJVMDIStrictMode()) {
723
arg = (Connector.StringArgument) arguments.get("options");
724
arg.setValue("strict=y");
725
}
726
*/
727
728
if (! argumentHandler.isDefaultDebugeeJavaHome()) {
729
arg = (Connector.StringArgument) arguments.get("home");
730
arg.setValue(argumentHandler.getDebugeeJavaHome());
731
}
732
733
if (! argumentHandler.isDefaultLaunchExecName()) {
734
arg = (Connector.StringArgument) arguments.get("vmexec");
735
arg.setValue(argumentHandler.getLaunchExecName());
736
}
737
738
String vmArgs = "";
739
740
String vmUserArgs = argumentHandler.getLaunchOptions();
741
742
if (vmUserArgs != null) {
743
vmArgs = vmUserArgs;
744
}
745
746
/*
747
if (classPath != null) {
748
vmArgs += " -classpath " + quote + classPath + quote;
749
}
750
*/
751
752
if (vmArgs.length() > 0) {
753
arg = (Connector.StringArgument) arguments.get("options");
754
arg.setValue(vmArgs);
755
}
756
757
display("Connector arguments:");
758
Iterator iterator = arguments.values().iterator();
759
while (iterator.hasNext()) {
760
display(" " + iterator.next());
761
}
762
return arguments;
763
}
764
765
/**
766
* Make proper arguments for RawLaunchingConnector.
767
*/
768
private Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> setupRawLaunchingConnector(LaunchingConnector connector,
769
String classToExecute,
770
String classPath) {
771
display("RawLaunchingConnector:");
772
display(" name: " + connector.name());
773
display(" description: " + connector.description());
774
display(" transport: " + connector.transport());
775
776
Hashtable<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = new Hashtable<java.lang.String, com.sun.jdi.connect.Connector.Argument>(connector.defaultArguments());
777
778
String connectorAddress;
779
String vmAddress;
780
781
if (argumentHandler.isSocketTransport()) {
782
connectorAddress = argumentHandler.getTransportPort();
783
vmAddress = argumentHandler.getDebugeeHost()
784
+ ":" + argumentHandler.getTransportPort();
785
} else if (argumentHandler.isShmemTransport() ) {
786
connectorAddress = argumentHandler.getTransportSharedName();
787
vmAddress=connectorAddress;
788
} else {
789
throw new TestBug("Undefined transport type for AttachingConnector");
790
}
791
792
Connector.Argument arg;
793
794
arg = (Connector.StringArgument) arguments.get("quote");
795
String quote = arg.value();
796
797
String javaCmdLine = makeCommandLineString(classToExecute, quote);
798
799
arg = (Connector.StringArgument) arguments.get("command");
800
arg.setValue(javaCmdLine);
801
802
arg = (Connector.StringArgument) arguments.get("address");
803
arg.setValue(connectorAddress);
804
805
display("Connector arguments:");
806
Iterator iterator = arguments.values().iterator();
807
while (iterator.hasNext()) {
808
display(" " + iterator.next());
809
}
810
return arguments;
811
}
812
813
/**
814
* Make proper arguments for AttachingConnector.
815
*/
816
private Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> setupAttachingConnector(AttachingConnector connector,
817
String classToExecute,
818
String classPath) {
819
display("AttachingConnector:");
820
display(" name: " + connector.name());
821
display(" description: " + connector.description());
822
display(" transport: " + connector.transport());
823
824
Hashtable<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = new Hashtable<java.lang.String,com.sun.jdi.connect.Connector.Argument>(connector.defaultArguments());
825
826
Connector.Argument arg;
827
if (argumentHandler.isSocketTransport()) {
828
arg = (Connector.StringArgument) arguments.get("hostname");
829
arg.setValue(argumentHandler.getDebugeeHost());
830
Connector.IntegerArgument iarg = (Connector.IntegerArgument) arguments.get("port");
831
iarg.setValue(argumentHandler.getTransportPortNumber());
832
} else {
833
arg = (Connector.StringArgument) arguments.get("name");
834
arg.setValue(argumentHandler.getTransportSharedName());
835
}
836
837
display("Connector arguments:");
838
Iterator iterator = arguments.values().iterator();
839
while (iterator.hasNext()) {
840
display(" " + iterator.next());
841
}
842
return arguments;
843
}
844
845
/**
846
* Make proper arguments for ListeningConnector.
847
*/
848
private Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> setupListeningConnector(ListeningConnector connector,
849
String classToExecute,
850
String classPath) {
851
display("ListeningConnector:");
852
display(" name: " + connector.name());
853
display(" description: " + connector.description());
854
display(" transport: " + connector.transport());
855
856
Hashtable<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = new Hashtable<java.lang.String,com.sun.jdi.connect.Connector.Argument>(connector.defaultArguments());
857
858
Connector.Argument arg;
859
if (argumentHandler.isSocketTransport()) {
860
if (!argumentHandler.isTransportAddressDynamic()) {
861
int port = argumentHandler.getTransportPortNumber();
862
Connector.IntegerArgument iarg = (Connector.IntegerArgument) arguments.get("port");
863
iarg.setValue(port);
864
}
865
} else {
866
String sharedName = argumentHandler.getTransportSharedName();
867
arg = (Connector.StringArgument) arguments.get("name");
868
arg.setValue(sharedName);
869
}
870
871
display("Connector arguments:");
872
Iterator iterator = arguments.values().iterator();
873
while (iterator.hasNext()) {
874
display(" " + iterator.next());
875
}
876
return arguments;
877
}
878
879
// -------------------------------------------------- //
880
881
/**
882
* Find connector by name from given connectors list.
883
*/
884
private Connector findConnector(String connectorName, List connectors) {
885
Iterator iter = connectors.iterator();
886
887
while (iter.hasNext()) {
888
Connector connector = (Connector) iter.next();
889
if (connector.name().equals(connectorName)) {
890
return connector;
891
}
892
}
893
throw new Failure("JDI connector not found: " + connectorName);
894
}
895
896
// -------------------------------------------------- //
897
898
/**
899
* Launch local debuggee process with specified command line arguments
900
* and make initial <code>Debugee</code> mirror.
901
*/
902
protected Debugee startLocalDebugee(String[] cmdArgs) {
903
Process process = null;
904
905
try {
906
process = launchProcess(cmdArgs);
907
} catch (IOException e) {
908
e.printStackTrace(log.getOutStream());
909
throw new Failure("Caught exception while launching local debuggee VM process:\n\t"
910
+ e);
911
}
912
913
return makeLocalDebugee(process);
914
}
915
916
/**
917
* Launch remote debuggee process with specified command line arguments
918
* and make initial <code>Debugee</code> mirror.
919
*/
920
protected RemoteLaunchedDebugee startRemoteDebugee(String[] cmdArgs) {
921
try {
922
launchRemoteProcess(cmdArgs);
923
} catch (IOException e) {
924
e.printStackTrace(log.getOutStream());
925
throw new Failure("Caught exception while launching remote debuggee VM process:\n\t"
926
+ e);
927
}
928
929
RemoteLaunchedDebugee debugee = new RemoteLaunchedDebugee(this);
930
931
Finalizer finalizer = new Finalizer(debugee);
932
finalizer.activate();
933
934
return debugee;
935
}
936
937
/**
938
* Launch manual debuggee process with specified command line arguments
939
* and make initial <code>Debugee</code> mirror.
940
*/
941
protected ManualLaunchedDebugee startManualDebugee(String cmd) {
942
ManualLaunchedDebugee debugee = new ManualLaunchedDebugee(this);
943
debugee.launchDebugee(cmd);
944
945
Finalizer finalizer = new Finalizer(debugee);
946
finalizer.activate();
947
948
return debugee;
949
}
950
951
public static String readVMStartExceptionOutput(VMStartException e, PrintStream log) {
952
StringBuffer msg = new StringBuffer();
953
try (InputStream is = e.process().getInputStream()) {
954
msg.append("\tstdout: ").append(new String(readAllBytes(is))).append('\n');
955
} catch (IOException e1) {
956
log.println("Could not read normal output from launched process:" + e1);
957
}
958
try (InputStream is = e.process().getErrorStream()) {
959
msg.append("\tstderr: ").append(new String(readAllBytes(is)));
960
} catch (IOException e1) {
961
log.println("Could not read error output from launched process:" + e1);
962
}
963
return msg.toString();
964
}
965
966
/**
967
* Copied from the JDK 9 implementation in InputStream.java
968
*/
969
private static byte[] readAllBytes(InputStream is) throws IOException {
970
final int DEFAULT_BUFFER_SIZE = 8192;
971
final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
972
973
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
974
int capacity = buf.length;
975
int nread = 0;
976
int n;
977
for (;;) {
978
// read to EOF which may read more or less than initial buffer size
979
while ((n = is.read(buf, nread, capacity - nread)) > 0)
980
nread += n;
981
982
// if the last call to read returned -1, then we're done
983
if (n < 0)
984
break;
985
986
// need to allocate a larger buffer
987
if (capacity <= MAX_BUFFER_SIZE - capacity) {
988
capacity = capacity << 1;
989
} else {
990
if (capacity == MAX_BUFFER_SIZE)
991
throw new OutOfMemoryError("Required array size too large");
992
capacity = MAX_BUFFER_SIZE;
993
}
994
buf = Arrays.copyOf(buf, capacity);
995
}
996
return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
997
}
998
999
}
1000
1001
1002
/**
1003
* Mirror of locally launched debugee.
1004
*/
1005
final class LocalLaunchedDebugee extends Debugee {
1006
1007
/** Enwrap the locally started VM process. */
1008
public LocalLaunchedDebugee (Process process, Binder binder) {
1009
super(binder);
1010
this.process = process;
1011
checkTermination = true;
1012
}
1013
1014
// ---------------------------------------------- //
1015
1016
/** Return exit status of the debugee VM. */
1017
public int getStatus () {
1018
return process.exitValue();
1019
}
1020
1021
/** Check whether the debugee VM has been terminated. */
1022
public boolean terminated () {
1023
if (process == null)
1024
return true;
1025
1026
try {
1027
int value = process.exitValue();
1028
return true;
1029
} catch (IllegalThreadStateException e) {
1030
return false;
1031
}
1032
}
1033
1034
// ---------------------------------------------- //
1035
1036
/** Kill the debugee VM. */
1037
protected void killDebugee () {
1038
super.killDebugee();
1039
if (!terminated()) {
1040
log.display("Killing debugee VM process");
1041
process.destroy();
1042
}
1043
}
1044
1045
/** Wait until the debugee VM shutdown or crash. */
1046
protected int waitForDebugee () throws InterruptedException {
1047
int code = process.waitFor();
1048
return code;
1049
}
1050
1051
/** Get a pipe to write to the debugee's stdin stream. */
1052
protected OutputStream getInPipe () {
1053
return process.getOutputStream();
1054
}
1055
1056
/** Get a pipe to read the debugee's stdout stream. */
1057
protected InputStream getOutPipe () {
1058
return process.getInputStream();
1059
}
1060
1061
/** Get a pipe to read the debugee's stderr stream. */
1062
protected InputStream getErrPipe () {
1063
return process.getErrorStream();
1064
}
1065
}
1066
1067
1068
/**
1069
* Mirror of remotely launched debugee.
1070
*/
1071
final class RemoteLaunchedDebugee extends Debugee {
1072
1073
/** Enwrap the remotely started VM process. */
1074
public RemoteLaunchedDebugee (Binder binder) {
1075
super(binder);
1076
}
1077
1078
// ---------------------------------------------- //
1079
1080
/** Return exit status of the debugee VM. */
1081
public int getStatus () {
1082
return binder.getRemoteProcessStatus();
1083
}
1084
1085
/** Check whether the debugee VM has been terminated. */
1086
public boolean terminated () {
1087
return binder.isRemoteProcessTerminated();
1088
}
1089
1090
// ---------------------------------------------- //
1091
1092
/** Kill the debugee VM. */
1093
protected void killDebugee () {
1094
super.killDebugee();
1095
if (!terminated()) {
1096
binder.killRemoteProcess();
1097
}
1098
}
1099
1100
/** Wait until the debugee VM shutdown or crash. */
1101
protected int waitForDebugee () {
1102
return binder.waitForRemoteProcess();
1103
}
1104
1105
/** Get a pipe to write to the debugee's stdin stream. */
1106
protected OutputStream getInPipe () {
1107
return null;
1108
}
1109
1110
/** Get a pipe to read the debugee's stdout stream. */
1111
protected InputStream getOutPipe () {
1112
return null;
1113
}
1114
1115
/** Get a pipe to read the debugee's stderr stream. */
1116
protected InputStream getErrPipe () {
1117
return null;
1118
}
1119
1120
public void redirectStdout(OutputStream out) {
1121
}
1122
1123
public void redirectStdout(Log log, String prefix) {
1124
}
1125
1126
public void redirectStderr(OutputStream out) {
1127
}
1128
1129
public void redirectStderr(Log log, String prefix) {
1130
}
1131
}
1132
1133
1134
/**
1135
* Mirror of manually launched debugee.
1136
*/
1137
final class ManualLaunchedDebugee extends Debugee {
1138
/** Enwrap the manually started VM process. */
1139
public ManualLaunchedDebugee (Binder binder) {
1140
super(binder);
1141
makeInputReader();
1142
}
1143
1144
// ---------------------------------------------- //
1145
1146
private int exitCode = 0;
1147
private boolean finished = false;
1148
private static BufferedReader bin = null;
1149
1150
public void launchDebugee(String commandLine) {
1151
makeInputReader();
1152
1153
putMessage("Launch target VM using such command line:\n"
1154
+ commandLine);
1155
String answer = askQuestion("Has the VM successfully started? (yes/no)", "yes");
1156
for ( ; ; ) {
1157
if (answer.equals("yes"))
1158
break;
1159
if (answer.equals("no"))
1160
throw new Failure ("Unable to manually launch debugee VM");
1161
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
1162
}
1163
}
1164
1165
private static void makeInputReader() {
1166
if (bin == null) {
1167
bin = new BufferedReader(new InputStreamReader(System.in));
1168
}
1169
}
1170
1171
private static void destroyInputReader() {
1172
if (bin != null) {
1173
try {
1174
bin.close();
1175
} catch (IOException e) {
1176
// e.printStackTrace(log.getOutStream());
1177
throw new Failure("Caught exception while closing input stream:\n\t" + e);
1178
}
1179
bin = null;
1180
}
1181
}
1182
1183
private static void putMessage(String msg) {
1184
System.out.println("\n>>> " + msg);
1185
}
1186
1187
private static String askQuestion(String question, String defaultAnswer) {
1188
try {
1189
System.out.print("\n>>> " + question);
1190
System.out.print(" [" + defaultAnswer + "] ");
1191
System.out.flush();
1192
String answer = bin.readLine();
1193
if (answer.equals(""))
1194
return defaultAnswer;
1195
return answer;
1196
} catch (IOException e) {
1197
// e.printStackTrace(log.getOutStream());
1198
throw new Failure("Caught exception while reading answer:\n\t" + e);
1199
}
1200
}
1201
1202
/** Return exit status of the debugee VM. */
1203
public int getStatus () {
1204
if (! finished) {
1205
throw new Failure("Unable to get status of debugee VM: process still alive");
1206
}
1207
return exitCode;
1208
}
1209
1210
/** Check whether the debugee VM has been terminated. */
1211
public boolean terminated () {
1212
return finished;
1213
}
1214
1215
// ---------------------------------------------- //
1216
1217
/** Kill the debugee VM. */
1218
protected void killDebugee () {
1219
super.killDebugee();
1220
if (!terminated()) {
1221
putMessage("Kill launched VM");
1222
String answer = askQuestion("Has the VM successfully terminated? (yes/no)", "yes");
1223
for ( ; ; ) {
1224
if (answer.equals("yes")) {
1225
finished = true;
1226
break;
1227
}
1228
if (answer.equals("no"))
1229
throw new Failure ("Unable to manually kill debugee VM");
1230
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
1231
}
1232
}
1233
}
1234
1235
/** Wait until the debugee VM shutdown or crash. */
1236
protected int waitForDebugee () {
1237
putMessage("Wait for launched VM to exit.");
1238
String answer = askQuestion("What is VM exit code?", "95");
1239
for ( ; ; ) {
1240
try {
1241
exitCode = Integer.parseInt(answer);
1242
break;
1243
} catch (NumberFormatException e) {
1244
answer = askQuestion("Wrong answer. Please type integer value", "95");
1245
}
1246
}
1247
finished = true;
1248
return exitCode;
1249
}
1250
1251
/** Get a pipe to write to the debugee's stdin stream. */
1252
protected OutputStream getInPipe () {
1253
return null;
1254
}
1255
1256
/** Get a pipe to read the debugee's stdout stream. */
1257
protected InputStream getOutPipe () {
1258
return null;
1259
}
1260
1261
/** Get a pipe to read the debugee's stderr stream. */
1262
protected InputStream getErrPipe () {
1263
return null;
1264
}
1265
1266
public void redirectStdout(OutputStream out) {
1267
}
1268
1269
public void redirectStdout(Log log, String prefix) {
1270
}
1271
1272
public void redirectStderr(OutputStream out) {
1273
}
1274
1275
public void redirectStderr(Log log, String prefix) {
1276
}
1277
1278
public void close() {
1279
destroyInputReader();
1280
super.close();
1281
}
1282
}
1283
1284