Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java
38920 views
1
/*
2
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package com.sun.tools.jdi;
27
28
import com.sun.tools.jdi.*;
29
import com.sun.jdi.connect.*;
30
import com.sun.jdi.connect.spi.*;
31
import com.sun.jdi.*;
32
33
import java.util.Map;
34
import java.util.StringTokenizer;
35
import java.util.List;
36
import java.util.ArrayList;
37
import java.io.IOException;
38
import java.io.InterruptedIOException;
39
40
abstract class AbstractLauncher extends ConnectorImpl implements LaunchingConnector {
41
42
abstract public VirtualMachine
43
launch(Map<String,? extends Connector.Argument> arguments)
44
throws IOException,
45
IllegalConnectorArgumentsException,
46
VMStartException;
47
abstract public String name();
48
abstract public String description();
49
50
ThreadGroup grp;
51
52
AbstractLauncher() {
53
super();
54
55
grp = Thread.currentThread().getThreadGroup();
56
ThreadGroup parent = null;
57
while ((parent = grp.getParent()) != null) {
58
grp = parent;
59
}
60
}
61
62
String[] tokenizeCommand(String command, char quote) {
63
String quoteStr = String.valueOf(quote); // easier to deal with
64
65
/*
66
* Tokenize the command, respecting the given quote character.
67
*/
68
StringTokenizer tokenizer = new StringTokenizer(command,
69
quote + " \t\r\n\f",
70
true);
71
String quoted = null;
72
String pending = null;
73
List<String> tokenList = new ArrayList<String>();
74
while (tokenizer.hasMoreTokens()) {
75
String token = tokenizer.nextToken();
76
if (quoted != null) {
77
if (token.equals(quoteStr)) {
78
tokenList.add(quoted);
79
quoted = null;
80
} else {
81
quoted += token;
82
}
83
} else if (pending != null) {
84
if (token.equals(quoteStr)) {
85
quoted = pending;
86
} else if ((token.length() == 1) &&
87
Character.isWhitespace(token.charAt(0))) {
88
tokenList.add(pending);
89
} else {
90
throw new InternalException("Unexpected token: " + token);
91
}
92
pending = null;
93
} else {
94
if (token.equals(quoteStr)) {
95
quoted = "";
96
} else if ((token.length() == 1) &&
97
Character.isWhitespace(token.charAt(0))) {
98
// continue
99
} else {
100
pending = token;
101
}
102
}
103
}
104
105
/*
106
* Add final token.
107
*/
108
if (pending != null) {
109
tokenList.add(pending);
110
}
111
112
/*
113
* An unclosed quote at the end of the command. Do an
114
* implicit end quote.
115
*/
116
if (quoted != null) {
117
tokenList.add(quoted);
118
}
119
120
String[] tokenArray = new String[tokenList.size()];
121
for (int i = 0; i < tokenList.size(); i++) {
122
tokenArray[i] = tokenList.get(i);
123
}
124
return tokenArray;
125
}
126
127
protected VirtualMachine launch(String[] commandArray, String address,
128
TransportService.ListenKey listenKey,
129
TransportService ts)
130
throws IOException, VMStartException {
131
Helper helper = new Helper(commandArray, address, listenKey, ts);
132
helper.launchAndAccept();
133
134
VirtualMachineManager manager =
135
Bootstrap.virtualMachineManager();
136
137
return manager.createVirtualMachine(helper.connection(),
138
helper.process());
139
}
140
141
/**
142
* This class simply provides a context for a single launch and
143
* accept. It provides instance fields that can be used by
144
* all threads involved. This stuff can't be in the Connector proper
145
* because the connector is a singleton and is not specific to any
146
* one launch.
147
*/
148
private class Helper {
149
private final String address;
150
private TransportService.ListenKey listenKey;
151
private TransportService ts;
152
private final String[] commandArray;
153
private Process process = null;
154
private Connection connection = null;
155
private IOException acceptException = null;
156
private boolean exited = false;
157
158
Helper(String[] commandArray, String address, TransportService.ListenKey listenKey,
159
TransportService ts) {
160
this.commandArray = commandArray;
161
this.address = address;
162
this.listenKey = listenKey;
163
this.ts = ts;
164
}
165
166
String commandString() {
167
String str = "";
168
for (int i = 0; i < commandArray.length; i++) {
169
if (i > 0) {
170
str += " ";
171
}
172
str += commandArray[i];
173
}
174
return str;
175
}
176
177
synchronized void launchAndAccept() throws
178
IOException, VMStartException {
179
180
process = Runtime.getRuntime().exec(commandArray);
181
182
Thread acceptingThread = acceptConnection();
183
Thread monitoringThread = monitorTarget();
184
try {
185
while ((connection == null) &&
186
(acceptException == null) &&
187
!exited) {
188
wait();
189
}
190
191
if (exited) {
192
throw new VMStartException(
193
"VM initialization failed for: " + commandString(), process);
194
}
195
if (acceptException != null) {
196
// Rethrow the exception in this thread
197
throw acceptException;
198
}
199
} catch (InterruptedException e) {
200
throw new InterruptedIOException("Interrupted during accept");
201
} finally {
202
acceptingThread.interrupt();
203
monitoringThread.interrupt();
204
}
205
}
206
207
Process process() {
208
return process;
209
}
210
211
Connection connection() {
212
return connection;
213
}
214
215
synchronized void notifyOfExit() {
216
exited = true;
217
notify();
218
}
219
220
synchronized void notifyOfConnection(Connection connection) {
221
this.connection = connection;
222
notify();
223
}
224
225
synchronized void notifyOfAcceptException(IOException acceptException) {
226
this.acceptException = acceptException;
227
notify();
228
}
229
230
Thread monitorTarget() {
231
Thread thread = new Thread(grp,
232
"launched target monitor") {
233
public void run() {
234
try {
235
process.waitFor();
236
/*
237
* Notify waiting thread of VM error termination
238
*/
239
notifyOfExit();
240
} catch (InterruptedException e) {
241
// Connection has been established, stop monitoring
242
}
243
}
244
};
245
thread.setDaemon(true);
246
thread.start();
247
return thread;
248
}
249
250
Thread acceptConnection() {
251
Thread thread = new Thread(grp,
252
"connection acceptor") {
253
public void run() {
254
try {
255
Connection connection = ts.accept(listenKey, 0, 0);
256
/*
257
* Notify waiting thread of connection
258
*/
259
notifyOfConnection(connection);
260
} catch (InterruptedIOException e) {
261
// VM terminated, stop accepting
262
} catch (IOException e) {
263
// Report any other exception to waiting thread
264
notifyOfAcceptException(e);
265
}
266
}
267
};
268
thread.setDaemon(true);
269
thread.start();
270
return thread;
271
}
272
}
273
}
274
275