Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/gc/logging/TestPrintReferences.java
40942 views
1
/*
2
* Copyright (c) 2015, 2020, 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 gc.logging;
25
26
/*
27
* @test TestPrintReferences
28
* @bug 8136991 8186402 8186465 8188245
29
* @summary Validate the reference processing logging
30
* @requires vm.gc.G1
31
* @library /test/lib
32
* @modules java.base/jdk.internal.misc
33
* java.management
34
* @run driver gc.logging.TestPrintReferences
35
*/
36
37
import java.lang.ref.SoftReference;
38
import java.math.BigDecimal;
39
import jdk.test.lib.process.OutputAnalyzer;
40
import jdk.test.lib.process.ProcessTools;
41
import java.util.regex.Pattern;
42
import java.util.regex.Matcher;
43
44
public class TestPrintReferences {
45
static String output;
46
static final String doubleRegex = "[0-9]+[.,][0-9]+";
47
static final String referenceProcessing = "Reference Processing";
48
static final String softReference = "SoftReference";
49
static final String weakReference = "WeakReference";
50
static final String finalReference = "FinalReference";
51
static final String phantomReference = "PhantomReference";
52
53
static final String phaseReconsiderSoftReferences = "Reconsider SoftReferences";
54
static final String phaseNotifySoftWeakReferences = "Notify Soft/WeakReferences";
55
static final String phaseNotifyKeepAliveFinalizer = "Notify and keep alive finalizable";
56
static final String phaseNotifyPhantomReferences = "Notify PhantomReferences";
57
58
static final String gcLogTimeRegex = ".* GC\\([0-9]+\\) ";
59
60
public static void main(String[] args) throws Exception {
61
testPhases(true);
62
testPhases(false);
63
testRefs();
64
}
65
66
static String indent(int count) {
67
return " {" + count + "}";
68
}
69
70
public static void testRefs() throws Exception {
71
ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder("-Xlog:gc+ref+phases=debug",
72
"-XX:+UseG1GC",
73
"-Xmx32M",
74
GCTest.class.getName());
75
OutputAnalyzer output = new OutputAnalyzer(pb_enabled.start());
76
77
checkRefsLogFormat(output);
78
79
output.shouldHaveExitValue(0);
80
}
81
82
private static String refRegex(String reftype) {
83
String countRegex = "[0-9]+";
84
return gcLogTimeRegex + indent(6) + reftype + ":\n" +
85
gcLogTimeRegex + indent(8) + "Discovered: " + countRegex + "\n" +
86
gcLogTimeRegex + indent(8) + "Cleared: " + countRegex + "\n";
87
}
88
89
private static void checkRefsLogFormat(OutputAnalyzer output) {
90
output.shouldMatch(refRegex("SoftReference") +
91
refRegex("WeakReference") +
92
refRegex("FinalReference") +
93
refRegex("PhantomReference"));
94
}
95
96
public static void testPhases(boolean parallelRefProcEnabled) throws Exception {
97
ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder("-Xlog:gc+phases+ref=debug",
98
"-XX:+UseG1GC",
99
"-Xmx32M",
100
"-XX:" + (parallelRefProcEnabled ? "+" : "-") + "ParallelRefProcEnabled",
101
"-XX:-UseDynamicNumberOfGCThreads",
102
"-XX:ParallelGCThreads=2",
103
GCTest.class.getName());
104
OutputAnalyzer output = new OutputAnalyzer(pb_enabled.start());
105
106
checkLogFormat(output, parallelRefProcEnabled);
107
checkLogValue(output);
108
109
output.shouldHaveExitValue(0);
110
}
111
112
private static String phaseRegex(String phaseName) {
113
final String timeRegex = doubleRegex + "ms";
114
return indent(6) + phaseName + ": " + timeRegex + "\n";
115
}
116
117
private static String subphaseRegex(String subphaseName, boolean parallelRefProcEnabled) {
118
final String timeRegex = "\\s+" + doubleRegex;
119
if (parallelRefProcEnabled) {
120
final String timeInParRegex = timeRegex +",\\s";
121
return gcLogTimeRegex + indent(8) + subphaseName +
122
" \\(ms\\):\\s+(Min:" + timeInParRegex + "Avg:" + timeInParRegex + "Max:" + timeInParRegex + "Diff:" + timeInParRegex + "Sum:" + timeInParRegex +
123
"Workers: [0-9]+|skipped)" + "\n";
124
} else {
125
return gcLogTimeRegex + indent(8) + subphaseName + ":(" + timeRegex + "ms|\\s+skipped)\n";
126
}
127
}
128
129
// Find the first Reference Processing log and check its format.
130
private static void checkLogFormat(OutputAnalyzer output, boolean parallelRefProcEnabled) {
131
String timeRegex = doubleRegex + "ms";
132
133
/* Total Reference processing time */
134
String totalRegex = gcLogTimeRegex + indent(4) + referenceProcessing + ": " + timeRegex + "\n";
135
136
String balanceRegex = parallelRefProcEnabled ? "(" + gcLogTimeRegex + indent(8) + "Balance queues: " + timeRegex + "\n)??" : "";
137
138
final boolean p = parallelRefProcEnabled;
139
140
String phase1Regex = gcLogTimeRegex + phaseRegex(phaseReconsiderSoftReferences) + balanceRegex + subphaseRegex("SoftRef", p);
141
String phase2Regex = gcLogTimeRegex + phaseRegex(phaseNotifySoftWeakReferences) +
142
balanceRegex +
143
subphaseRegex("SoftRef", p) +
144
subphaseRegex("WeakRef", p) +
145
subphaseRegex("FinalRef", p) +
146
subphaseRegex("Total", p);
147
String phase3Regex = gcLogTimeRegex + phaseRegex(phaseNotifyKeepAliveFinalizer) + balanceRegex + subphaseRegex("FinalRef", p);
148
String phase4Regex = gcLogTimeRegex + phaseRegex(phaseNotifyPhantomReferences) + balanceRegex + subphaseRegex("PhantomRef", p);
149
150
output.shouldMatch(totalRegex +
151
phase1Regex +
152
phase2Regex +
153
phase3Regex +
154
phase4Regex);
155
}
156
157
// After getting time value, update 'output' for next use.
158
private static BigDecimal getTimeValue(String name, int indentCount) {
159
// Pattern of 'name', 'value' and some extra strings.
160
String patternString = gcLogTimeRegex + indent(indentCount) + name + ": " + "(" + doubleRegex + ")";
161
Matcher m = Pattern.compile(patternString).matcher(output);
162
if (!m.find()) {
163
throw new RuntimeException("Could not find time log for " + patternString);
164
}
165
166
String match = m.group();
167
String value = m.group(1);
168
169
double result = Double.parseDouble(value);
170
171
int index = output.indexOf(match);
172
if (index != -1) {
173
output = output.substring(index, output.length());
174
}
175
176
// Convert to BigDecimal to control the precision of floating point arithmetic.
177
return BigDecimal.valueOf(result);
178
}
179
180
// Reference log is printing 1 decimal place of elapsed time.
181
// So sum of each sub-phases could be slightly larger than the enclosing phase in some cases.
182
// Because of this we need method to verify that our measurements and calculations are valid.
183
private static boolean greaterThanOrApproximatelyEqual(BigDecimal phaseTime, BigDecimal sumOfSubPhasesTime, BigDecimal tolerance) {
184
if (phaseTime.compareTo(sumOfSubPhasesTime) >= 0) {
185
// phaseTime is greater than or equal.
186
return true;
187
}
188
189
BigDecimal diff = sumOfSubPhasesTime.subtract(phaseTime);
190
if (diff.compareTo(tolerance) <= 0) {
191
// Difference is within tolerance, so approximately equal.
192
return true;
193
}
194
195
// sumOfSubPhasesTime is greater than phaseTime and not within tolerance.
196
return false;
197
}
198
199
// Find the first concurrent Reference Processing log and compare phase time vs. sum of sub-phases.
200
public static void checkLogValue(OutputAnalyzer out) {
201
output = out.getStdout();
202
203
String patternString = gcLogTimeRegex + indent(0) +
204
referenceProcessing + ": " + "[0-9]+[.,][0-9]+";
205
Matcher m = Pattern.compile(patternString).matcher(output);
206
if (m.find()) {
207
int start = m.start();
208
int end = output.length();
209
// If there's another concurrent Reference Processing log, ignore it.
210
if (m.find()) {
211
end = m.start();
212
}
213
if (start != -1) {
214
output = output.substring(start, end);
215
checkTrimmedLogValue();
216
}
217
}
218
}
219
220
private static void checkTrimmedLogValue() {
221
BigDecimal refProcTime = getTimeValue(referenceProcessing, 0);
222
223
BigDecimal sumOfSubPhasesTime = getTimeValue(phaseReconsiderSoftReferences, 2);
224
sumOfSubPhasesTime = sumOfSubPhasesTime.add(getTimeValue(phaseNotifySoftWeakReferences, 2));
225
sumOfSubPhasesTime = sumOfSubPhasesTime.add(getTimeValue(phaseNotifyKeepAliveFinalizer, 2));
226
sumOfSubPhasesTime = sumOfSubPhasesTime.add(getTimeValue(phaseNotifyPhantomReferences, 2));
227
228
// If there are 4 phases, we should allow 0.2 tolerance.
229
final BigDecimal toleranceFor4SubPhases = BigDecimal.valueOf(0.2);
230
if (!greaterThanOrApproximatelyEqual(refProcTime, sumOfSubPhasesTime, toleranceFor4SubPhases)) {
231
throw new RuntimeException("Reference Processing time(" + refProcTime + "ms) is less than the sum("
232
+ sumOfSubPhasesTime + "ms) of each phases");
233
}
234
}
235
236
static class GCTest {
237
static final int SIZE = 512 * 1024;
238
static Object[] dummy = new Object[SIZE];
239
240
public static void main(String [] args) {
241
for (int i = 0; i < SIZE; i++) {
242
dummy[i] = new SoftReference<>(new Object());
243
}
244
}
245
}
246
}
247
248