Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AbstractJarAgent.java
41161 views
1
/*
2
* Copyright (c) 2008, 2018, 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
package nsk.share.aod;
24
25
import java.lang.instrument.*;
26
import java.io.*;
27
import nsk.share.*;
28
29
/*
30
31
AbstractJarAgent is base class for java agents used in AttachOnDemand tests
32
(tests against Attach API, API from package com.sun.tools.attach).
33
34
In all AttachOnDemand tests the same algorithm is used:
35
- java application where agent is loaded to (target application) based on
36
class nsk.share.aod.TargetApplicationWaitingAgents starts and waits when
37
test agents will be loaded
38
39
- special application (nsk.share.jvmti.aod.AgentsAttacher) loads test agents
40
in the target application using Attach API
41
42
- when agent is loaded it notifies target application about that and executes
43
test-specific actions. When agent execution is completed it also notifies
44
target application about that
45
46
- when all test agents finish execution target application checks its status
47
(passed or failed) and also finishes
48
49
Each java agent should have method 'agentmain' where only agent initialization should be done,
50
main agent's actions should be executed in special thread started from 'agentmain'.
51
Class AbstractJarAgent incapsulates actions common for all java agents: agent initialization,
52
starting thread executing agent's actions and communication with target application.
53
54
In most cases test agents should override only method 'agentActions' and its 'agentmain'
55
should contain only call of the method 'AbstractJarAgent.runJarAgent'.
56
57
Typical agent class looks like this:
58
59
public class agentExample extends AbstractJarAgent {
60
61
protected void init(String[] args) {
62
// parse agent's options and do test-specific initialization
63
}
64
65
protected void agentActions() {
66
// do test specific actions
67
}
68
69
public static void agentmain(final String options, Instrumentation inst) {
70
new agentExample().runJarAgent(options, inst);
71
}
72
}
73
*/
74
abstract public class AbstractJarAgent {
75
76
private boolean finishedSuccessfully = true;
77
78
private Log log;
79
80
protected void display(String message) {
81
log.display(outputPrefix + message);
82
}
83
84
protected void complain(String message) {
85
log.complain(outputPrefix + message);
86
}
87
88
protected void logThrowable(Throwable t) {
89
t.printStackTrace(log.getOutStream());
90
}
91
92
/*
93
* Instrumentation object passed to the 'agentmain' method
94
*/
95
protected Instrumentation inst;
96
97
private String name;
98
99
private String outputPrefix;
100
101
private String pathToNewByteCode;
102
103
protected String pathToNewByteCode() {
104
return pathToNewByteCode;
105
}
106
107
/*
108
* Subclasses should report about test failures using this method
109
*/
110
protected void setStatusFailed(String errorMessage) {
111
finishedSuccessfully = false;
112
complain("ERROR: " + errorMessage);
113
}
114
115
/*
116
* Initialization method, called from agentmain before method agentActions is called
117
* (it introduced for overriding in subclasses)
118
*/
119
protected void init(String[] args) {
120
}
121
122
protected static class AgentOption {
123
public String name;
124
public String value;
125
public AgentOption(String name, String value) {
126
this.name = name;
127
this.value = value;
128
}
129
}
130
131
protected AgentOption parseAgentArgument(String arg) {
132
int index = arg.indexOf('=');
133
if (index <= 0) {
134
throw new TestBug("Invalid agent parameters format");
135
}
136
return new AgentOption(arg.substring(0, index), arg.substring(index + 1));
137
}
138
139
static protected final String agentNameOption = "-agentName";
140
141
static protected final String pathToNewByteCodeOption = "-pathToNewByteCode";
142
143
/*
144
* Parse agent's options, initialize common parameters
145
*/
146
private void defaultInit(String[] args) {
147
for (int i = 0; i < args.length; i++) {
148
AgentOption option = parseAgentArgument(args[i]);
149
if (option.name.equals(agentNameOption)) {
150
name = option.value;
151
outputPrefix = name + ": ";
152
} else if (option.name.equals(pathToNewByteCodeOption)) {
153
pathToNewByteCode = option.value;
154
}
155
}
156
157
if (name == null)
158
throw new TestBug("Agent name wasn't specified");
159
160
log = new Log(System.out, true);
161
}
162
163
/*
164
* Special thread which is started from agentmain method and executing main
165
* agent's actions. When agent completes execution AgentThread notifies
166
* target application about that.
167
*/
168
class AgentThread extends Thread {
169
170
AgentThread() {
171
super("Jar agent thread (agent: " + name + ")");
172
}
173
174
public void run() {
175
try {
176
agentActions();
177
} catch (Throwable t) {
178
setStatusFailed("Unexpected exception in the JarAgent: " + t);
179
logThrowable(t);
180
} finally {
181
TargetApplicationWaitingAgents.agentFinished(name, finishedSuccessfully);
182
}
183
}
184
}
185
186
/*
187
* This methods parses agent's options, initializes agent, notifies target application
188
* that agent is started and starts thread executing main agent's actions.
189
* Agents used in AttachOnDemand tests should call this method from its agentmain methods.
190
*/
191
public final void runJarAgent(String options, Instrumentation inst) {
192
if (options == null)
193
throw new TestBug("Agent options weren't specified");
194
195
this.inst = inst;
196
197
String[] args = options.split(" ");
198
199
// initialize common parameters
200
defaultInit(args);
201
202
// test-specific initialization
203
init(args);
204
205
// notify target application that agent was loaded and initialized
206
TargetApplicationWaitingAgents.agentLoaded(name);
207
208
// start special thread executing test-specific actions
209
new AgentThread().start();
210
}
211
212
/*
213
* Actions specific for test should be realized in this method.
214
* This method is called from special thread started from agentmain method
215
* after agent initialization
216
*/
217
abstract protected void agentActions() throws Throwable;
218
219
220
/*
221
* Create ClassDefinition object for given class, path to the new class file
222
* is specified in the parameter 'pathToByteCode'
223
*/
224
protected static ClassDefinition createClassDefinition(Class<?> klass,
225
String pathToByteCode) throws IOException {
226
File classFile = new File(pathToByteCode + File.separator +
227
klass.getName().replace(".", File.separator) +
228
".class");
229
230
if (classFile.length() > Integer.MAX_VALUE)
231
throw new Failure("Class file '" + classFile.getName() + " 'too large");
232
233
byte data[] = new byte[(int)classFile.length()];
234
235
DataInputStream in = null;
236
try {
237
in = new DataInputStream(new FileInputStream(classFile));
238
in.readFully(data);
239
} finally {
240
if (in != null)
241
in.close();
242
}
243
244
return new ClassDefinition(klass, data);
245
}
246
247
/*
248
* Redefine given class using path to byte code specified with options -pathToNewByteCode
249
*/
250
protected void redefineClass(Class<?> klass) throws Throwable {
251
if (pathToNewByteCode() == null)
252
throw new TestBug("Path to new class files wasn't specified");
253
254
ClassDefinition newClassDef = createClassDefinition(klass, pathToNewByteCode());
255
inst.redefineClasses(newClassDef);
256
}
257
}
258
259