author | iklam |
Tue, 26 Mar 2019 11:34:40 -0700 | |
changeset 54297 | f98f158c1db8 |
parent 52125 | 28375a1de254 |
permissions | -rw-r--r-- |
48138 | 1 |
/* |
54297
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
2 |
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. |
48138 | 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 |
||
25 |
/* |
|
26 |
* @test |
|
27 |
* @summary Exercise the java.lang.instrument.Instrumentation APIs on classes archived |
|
28 |
* using CDS/AppCDSv1/AppCDSv2. |
|
29 |
* @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes |
|
48469
7312ae4465d6
8193672: [test] Enhance vm.cds property to check for all conditions required to run CDS tests
iklam
parents:
48403
diff
changeset
|
30 |
* @requires vm.cds |
48138 | 31 |
* @requires vm.flavor != "minimal" |
32 |
* @build sun.hotspot.WhiteBox |
|
33 |
* InstrumentationApp |
|
34 |
* InstrumentationClassFileTransformer |
|
35 |
* InstrumentationRegisterClassFileTransformer |
|
36 |
* @run main/othervm InstrumentationTest |
|
37 |
*/ |
|
38 |
||
39 |
// Note: TestCommon is from /test/hotspot/jtreg/runtime/appcds/TestCommon.java |
|
40 |
// Note: Util is from /test/hotspot/jtreg/runtime/appcds/test-classes/TestCommon.java |
|
41 |
||
42 |
import com.sun.tools.attach.VirtualMachine; |
|
43 |
import java.io.File; |
|
54297
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
44 |
import java.io.FileInputStream; |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
45 |
import java.util.Scanner; |
48138 | 46 |
import jdk.test.lib.Asserts; |
47 |
import jdk.test.lib.cds.CDSOptions; |
|
48 |
import jdk.test.lib.process.OutputAnalyzer; |
|
49 |
import jdk.test.lib.process.ProcessTools; |
|
50 |
||
51 |
public class InstrumentationTest { |
|
52 |
public static String bootClasses[] = { |
|
53 |
"InstrumentationApp$Intf", |
|
54 |
"InstrumentationApp$Bar", |
|
55 |
"sun.hotspot.WhiteBox", |
|
56 |
}; |
|
57 |
public static String appClasses[] = { |
|
58 |
"InstrumentationApp", |
|
59 |
"InstrumentationApp$Foo", |
|
60 |
"InstrumentationApp$MyLoader", |
|
61 |
}; |
|
62 |
public static String custClasses[] = { |
|
63 |
"InstrumentationApp$Coo", |
|
64 |
}; |
|
65 |
public static String sharedClasses[] = TestCommon.concat(bootClasses, appClasses); |
|
66 |
||
67 |
public static String agentClasses[] = { |
|
68 |
"InstrumentationClassFileTransformer", |
|
69 |
"InstrumentationRegisterClassFileTransformer", |
|
70 |
"Util", |
|
71 |
}; |
|
72 |
||
73 |
public static void main(String[] args) throws Throwable { |
|
74 |
runTest(false); |
|
75 |
runTest(true); |
|
76 |
} |
|
77 |
||
78 |
public static void runTest(boolean attachAgent) throws Throwable { |
|
79 |
String bootJar = |
|
80 |
ClassFileInstaller.writeJar("InstrumentationBoot.jar", bootClasses); |
|
81 |
String appJar = |
|
82 |
ClassFileInstaller.writeJar("InstrumentationApp.jar", |
|
83 |
TestCommon.concat(appClasses, |
|
84 |
"InstrumentationApp$ArchivedIfAppCDSv2Enabled")); |
|
85 |
String custJar = |
|
86 |
ClassFileInstaller.writeJar("InstrumentationCust.jar", custClasses); |
|
87 |
String agentJar = |
|
88 |
ClassFileInstaller.writeJar("InstrumentationAgent.jar", |
|
89 |
ClassFileInstaller.Manifest.fromSourceFile("InstrumentationAgent.mf"), |
|
90 |
agentClasses); |
|
91 |
||
92 |
String bootCP = "-Xbootclasspath/a:" + bootJar; |
|
93 |
||
94 |
System.out.println(""); |
|
95 |
System.out.println("============================================================"); |
|
96 |
System.out.println("CDS: NO, attachAgent: " + (attachAgent ? "YES" : "NO")); |
|
97 |
System.out.println("============================================================"); |
|
98 |
System.out.println(""); |
|
99 |
||
100 |
String agentCmdArg, flagFile; |
|
101 |
if (attachAgent) { |
|
102 |
// we will attach the agent, so don't specify -javaagent in the command line. We'll use |
|
103 |
// something harmless like -showversion to make it easier to construct the command line |
|
104 |
agentCmdArg = "-showversion"; |
|
105 |
} else { |
|
106 |
agentCmdArg = "-javaagent:" + agentJar; |
|
107 |
} |
|
108 |
||
109 |
// First, run the test class directly, w/o sharing, as a baseline reference |
|
110 |
flagFile = getFlagFile(attachAgent); |
|
111 |
AgentAttachThread t = doAttach(attachAgent, flagFile, agentJar); |
|
112 |
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( |
|
113 |
bootCP, |
|
114 |
"-cp", appJar, |
|
115 |
"-XX:+UnlockDiagnosticVMOptions", |
|
116 |
"-XX:+WhiteBoxAPI", |
|
117 |
"-Xshare:off", |
|
118 |
agentCmdArg, |
|
52125
28375a1de254
8212028: Use run-test makefile framework for testing in Oracle's Mach5
erikj
parents:
48469
diff
changeset
|
119 |
"InstrumentationApp", flagFile, bootJar, appJar, custJar); |
48138 | 120 |
TestCommon.executeAndLog(pb, "no-sharing").shouldHaveExitValue(0); |
121 |
checkAttach(t); |
|
122 |
||
123 |
// Dump the AppCDS archive. On some platforms AppCDSv2 may not be enabled, so we |
|
124 |
// first try the v2 classlist, and if that fails, revert to the v1 classlist. |
|
125 |
// Note that the InstrumentationApp$ArchivedIfAppCDSv2Enabled class is archived |
|
126 |
// only if V2 is enabled. This is tested by InstrumentationApp.isAppCDSV2Enabled(). |
|
127 |
String[] v2Classes = { |
|
128 |
"InstrumentationApp$ArchivedIfAppCDSv2Enabled", |
|
129 |
"java/lang/Object id: 0", |
|
130 |
"InstrumentationApp$Intf id: 1", |
|
131 |
"InstrumentationApp$Coo id: 2 super: 0 interfaces: 1 source: " + custJar, |
|
132 |
}; |
|
133 |
String[] sharedClassesWithV2 = TestCommon.concat(v2Classes, sharedClasses); |
|
134 |
OutputAnalyzer out = TestCommon.dump(appJar, sharedClassesWithV2, bootCP); |
|
135 |
if (out.getExitValue() != 0) { |
|
136 |
System.out.println("Redumping with AppCDSv2 disabled"); |
|
137 |
TestCommon.testDump(appJar, sharedClasses, bootCP); |
|
138 |
} |
|
139 |
||
140 |
// Run with AppCDS. |
|
141 |
System.out.println(""); |
|
142 |
System.out.println("============================================================"); |
|
143 |
System.out.println("CDS: YES, attachAgent: " + (attachAgent ? "YES" : "NO")); |
|
144 |
System.out.println("============================================================"); |
|
145 |
System.out.println(""); |
|
146 |
||
147 |
flagFile = getFlagFile(attachAgent); |
|
148 |
t = doAttach(attachAgent, flagFile, agentJar); |
|
149 |
out = TestCommon.execAuto("-cp", appJar, |
|
150 |
bootCP, |
|
151 |
"-XX:+UnlockDiagnosticVMOptions", |
|
152 |
"-XX:+WhiteBoxAPI", |
|
153 |
agentCmdArg, |
|
52125
28375a1de254
8212028: Use run-test makefile framework for testing in Oracle's Mach5
erikj
parents:
48469
diff
changeset
|
154 |
"InstrumentationApp", flagFile, bootJar, appJar, custJar); |
48138 | 155 |
|
156 |
CDSOptions opts = (new CDSOptions()).setXShareMode("auto"); |
|
157 |
TestCommon.checkExec(out, opts); |
|
158 |
checkAttach(t); |
|
159 |
} |
|
160 |
||
161 |
static int flagFileSerial = 1; |
|
162 |
static private String getFlagFile(boolean attachAgent) { |
|
163 |
if (attachAgent) { |
|
164 |
// Do not reuse the same file name as Windows may fail to |
|
165 |
// delete the file. |
|
166 |
return "attach.flag." + ProcessHandle.current().pid() + |
|
167 |
"." + (flagFileSerial++) + "." + System.currentTimeMillis(); |
|
168 |
} else { |
|
169 |
return "noattach"; |
|
170 |
} |
|
171 |
} |
|
172 |
||
173 |
static AgentAttachThread doAttach(boolean attachAgent, String flagFile, String agentJar) throws Throwable { |
|
174 |
if (!attachAgent) { |
|
175 |
return null; |
|
176 |
} |
|
177 |
||
54297
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
178 |
// Hand-shake protocol with the child process |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
179 |
// [1] Parent process (this process) launches child process (InstrumentationApp) |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
180 |
// and then waits until child process writes its pid into the flagFile. |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
181 |
// [2] Child process process starts up, writes its pid into the flagFile, |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
182 |
// and waits for the flagFile to be deleted. |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
183 |
// [3] When parent process gets the pid, it attaches to the child process |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
184 |
// (if we attempt to attach to a process too early, the SIGQUIT |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
185 |
// may cause the child to die) and deletes the flagFile. |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
186 |
// [4] Child process resumes execution. |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
187 |
|
48138 | 188 |
File f = new File(flagFile); |
54297
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
189 |
f.delete(); |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
190 |
if (f.exists()) { |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
191 |
throw new RuntimeException("Flag file should not exist: " + f); |
48138 | 192 |
} |
193 |
||
194 |
// At this point, the child process is not yet launched. Note that |
|
195 |
// TestCommon.exec() and OutputAnalyzer.OutputAnalyzer() both block |
|
196 |
// until the child process has finished. |
|
197 |
// |
|
54297
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
198 |
// So, we will launch a AgentAttachThread which will poll the flagFile |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
199 |
// until the child process is launched. |
48138 | 200 |
AgentAttachThread t = new AgentAttachThread(flagFile, agentJar); |
201 |
t.start(); |
|
202 |
return t; |
|
203 |
} |
|
204 |
||
205 |
static void checkAttach(AgentAttachThread thread) throws Throwable { |
|
206 |
if (thread != null) { |
|
207 |
thread.check(); |
|
208 |
} |
|
209 |
} |
|
210 |
||
211 |
static class AgentAttachThread extends Thread { |
|
212 |
String flagFile; |
|
213 |
String agentJar; |
|
214 |
volatile boolean succeeded; |
|
215 |
||
216 |
AgentAttachThread(String flagFile, String agentJar) { |
|
217 |
this.flagFile = flagFile; |
|
218 |
this.agentJar = agentJar; |
|
219 |
this.succeeded = false; |
|
220 |
} |
|
221 |
||
222 |
static String getPid(String flagFile) throws Throwable { |
|
223 |
while (true) { |
|
224 |
// Keep polling until the child process has been launched. If for some |
|
225 |
// reason the child process fails to launch, this test will be terminated |
|
226 |
// by JTREG's time-out mechanism. |
|
227 |
Thread.sleep(100); |
|
54297
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
228 |
File f = new File(flagFile); |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
229 |
if (f.exists() && f.length() > 100) { |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
230 |
try (FileInputStream in = new FileInputStream(f)) { |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
231 |
Scanner scanner = new Scanner(in); |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
232 |
return Long.toString(scanner.nextLong()); |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
233 |
} catch (Throwable t) { |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
234 |
// This may happen on Windows if the child process has not |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
235 |
// fully closed the output stream to the flagFile |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
236 |
System.out.println("Ignored: " + t); |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
237 |
t.printStackTrace(System.out); |
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
238 |
continue; |
48138 | 239 |
} |
240 |
} |
|
241 |
} |
|
242 |
} |
|
243 |
||
244 |
public void run() { |
|
245 |
try { |
|
246 |
String pid = getPid(flagFile); |
|
54297
f98f158c1db8
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
iklam
parents:
52125
diff
changeset
|
247 |
System.out.println("child pid = " + pid); |
48138 | 248 |
VirtualMachine vm = VirtualMachine.attach(pid); |
249 |
System.out.println(agentJar); |
|
250 |
vm.loadAgent(agentJar); |
|
251 |
} catch (Throwable t) { |
|
252 |
t.printStackTrace(); |
|
253 |
throw new RuntimeException(t); |
|
254 |
} |
|
255 |
||
256 |
// Delete the flagFile to indicate to the child process that we |
|
257 |
// have attached to it, so it should proceed. |
|
258 |
File f = new File(flagFile); |
|
259 |
for (int i=0; i<5; i++) { |
|
260 |
// The detele may fail on Windows if the child JVM is checking |
|
261 |
// f.exists() at exactly the same time?? Let's do a little |
|
262 |
// dance. |
|
263 |
f.delete(); |
|
264 |
try { |
|
265 |
Thread.sleep(10); |
|
266 |
} catch (Throwable t) {;} |
|
267 |
} |
|
268 |
if (f.exists()) { |
|
269 |
throw new RuntimeException("Failed to delete " + f); |
|
270 |
} |
|
271 |
System.out.println("Attach succeeded (parent)"); |
|
272 |
succeeded = true; |
|
273 |
} |
|
274 |
||
275 |
void check() throws Throwable { |
|
276 |
super.join(); |
|
277 |
if (!succeeded) { |
|
278 |
throw new RuntimeException("Attaching agent to child VM failed"); |
|
279 |
} |
|
280 |
} |
|
281 |
} |
|
282 |
} |
|
283 |