Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/GetLocalVariable/GetLocalWithoutSuspendTest.java
41153 views
1
/*
2
* Copyright (c) 2020 SAP SE. 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
/**
25
* @test
26
* @bug 8249293
27
*
28
* @summary Test if stack walk to get local variable in the JVMTI implementation is safe if the
29
* target thread is not suspended.
30
*
31
* @comment The main/target thread uses recursion to build a large stack, then
32
* calls a native method to notify the JVMTI agent thread to get a
33
* local variable deep in the stack. This prolongs the stack walk. The
34
* target thread's stack is walkable while in native. After sending the
35
* notification it waits a while to give the agent time to reach the
36
* stack walk, then it returns from native. This is when its stack
37
* becomes not walkable again.
38
*
39
* @library /test/lib
40
* @compile GetLocalWithoutSuspendTest.java
41
* @run main/othervm/native
42
* -agentlib:GetLocalWithoutSuspendTest
43
* -Xbatch
44
* GetLocalWithoutSuspendTest
45
*/
46
47
public class GetLocalWithoutSuspendTest {
48
49
public static final int M = 1 << 20;
50
51
public static final int TEST_ITERATIONS = 200;
52
53
/**
54
* Native method to notify the agent thread to call GetLocalObject() on this thread.
55
*
56
* @param depth Depth of target frame for GetLocalObject() call. Should be
57
* large value to prolong the unsafe stack walk.
58
* @param waitTime Time to wait after notify with
59
* walkable stack before returning an becoming unsafe again.
60
* @return Dummy value.
61
*/
62
public static native void notifyAgentToGetLocal(int depth, int waitTime);
63
64
/**
65
* Notify agent thread that we are shutting down and wait for it to terminate.
66
*/
67
public static native void shutDown();
68
69
/**
70
* Provide agent thread with reference to target thread.
71
* @param target The target thread
72
*/
73
public static native void setTargetThread(Thread target);
74
75
public static void main(String[] args) throws Exception {
76
new GetLocalWithoutSuspendTest().runTest();
77
}
78
79
/**
80
* Wait cycles in native, i.e. with walkable stack, after notifying agent
81
* thread to do GetLocalObject() call.
82
*/
83
public int waitCycles = 1;
84
85
public void runTest() throws Exception {
86
log("Set target thread for get local variable calls by agent.");
87
setTargetThread(Thread.currentThread());
88
89
log("Test how many frames fit on the stack by performing recursive calls until");
90
log("StackOverflowError is thrown");
91
int targetDepth = recursiveMethod(0, M);
92
log("Testing with target depth: " + targetDepth);
93
94
log("Begin Test.");
95
long start = System.currentTimeMillis();
96
for (int iterations = 0; iterations < TEST_ITERATIONS; iterations++) {
97
long now = System.currentTimeMillis();
98
log((now - start) + " ms Iteration : " + iterations +
99
" waitTime : " + waitCycles);
100
int newTargetDepth = recursiveMethod(0, targetDepth);
101
if (newTargetDepth < targetDepth) {
102
// A StackOverflowError can occur due to (re-)compilation. We
103
// don't reach the native method notifyAgentToGetLocal() then
104
// which is a prerequisite to trigger the problematic race
105
// condition. So we reduce the targetDepth to avoid stack
106
// overflow.
107
log("StackOverflowError during test.");
108
log("Old target depth: " + targetDepth);
109
log("Retry with new target depth: " + newTargetDepth);
110
targetDepth = newTargetDepth;
111
}
112
iterations++;
113
// Double wait time, but limit to roughly 10^6 cycles.
114
waitCycles = (waitCycles << 1) & (M - 1);
115
waitCycles = waitCycles == 0 ? 1 : waitCycles;
116
}
117
118
// Notify agent thread that we are shutting down and wait for it to terminate.
119
shutDown();
120
121
log("Successfully finished test");
122
}
123
124
/**
125
* Perform recursive calls until the target stack depth is reached or the stack overflows.
126
* Call {@link #notifyAgentToGetLocal(int, int)} if the target depth is reached.
127
*
128
* @param depth Current recursion depth
129
* @param targetStackDepth Target recursion depth
130
* @return Depth at which the recursion was ended
131
*/
132
public int recursiveMethod(int depth, int targetStackDepth) {
133
int maxDepth = depth;
134
try {
135
if (depth == targetStackDepth) {
136
notifyAgentToGetLocal(depth - 100, waitCycles);
137
} else {
138
maxDepth = recursiveMethod(depth + 1, targetStackDepth);
139
}
140
} catch (StackOverflowError e) {
141
// Don't print message here, because this would likely trigger a new StackOverflowError
142
}
143
return maxDepth;
144
}
145
146
public static void log(String m) {
147
System.out.println("### Java-Test: " + m);
148
}
149
}
150
151