Skip to content

Commit f0d119a

Browse files
olivergillespieshipilev
authored andcommitted
8306929: Avoid CleanClassLoaderDataMetaspaces safepoints when previous versions are shared
8307448: Test RedefineSharedClassJFR fail due to wrong assumption Reviewed-by: shade Backport-of: 408cec516bb5fd82fb6dcddeee934ac0c5ecffaf
1 parent 9f35b5e commit f0d119a

File tree

2 files changed

+116
-5
lines changed

2 files changed

+116
-5
lines changed

test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefinePreviousVersions.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
/*
2525
* @test
2626
* @bug 8165246 8010319
27-
* @summary Test has_previous_versions flag and processing during class unloading.
27+
* @summary Test clean_previous_versions flag and processing during class unloading.
2828
* @requires vm.jvmti
2929
* @requires vm.opt.final.ClassUnloading
3030
* @requires vm.flagless
@@ -86,15 +86,15 @@ public static void main(String[] args) throws Exception {
8686
"-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
8787
"RedefinePreviousVersions");
8888
new OutputAnalyzer(pb.start())
89-
.shouldContain("Class unloading: has_previous_versions = false")
90-
.shouldContain("Class unloading: has_previous_versions = true")
89+
.shouldContain("Class unloading: should_clean_previous_versions = false")
90+
.shouldContain("Class unloading: should_clean_previous_versions = true")
9191
.shouldHaveExitValue(0);
9292
return;
9393
}
9494

9595
// Redefine a class and create some garbage
9696
// Since there are no methods running, the previous version is never added to the
97-
// previous_version_list and the flag _has_previous_versions should stay false
97+
// previous_version_list and the flag _should_clean_previous_versions should stay false
9898
RedefineClassHelper.redefineClass(RedefinePreviousVersions_B.class, newB);
9999

100100
for (int i = 0; i < 10 ; i++) {
@@ -114,7 +114,7 @@ public void run() {
114114
}
115115

116116
// Since a method of newRunning is running, this class should be added to the previous_version_list
117-
// of Running, and _has_previous_versions should return true at class unloading.
117+
// of Running, and _should_clean_previous_versions should return true at class unloading.
118118
RedefineClassHelper.redefineClass(RedefinePreviousVersions_Running.class, newRunning);
119119

120120
for (int i = 0; i < 10 ; i++) {
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (c) 2023, 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+
/*
25+
* @test
26+
* @bug 8306929
27+
* @summary Verify should_clean_previous_versions when run with JFR and CDS
28+
* @requires vm.jvmti
29+
* @requires vm.cds
30+
* @requires vm.hasJFR
31+
* @requires vm.opt.final.ClassUnloading
32+
* @requires vm.flagless
33+
* @library /test/lib
34+
* @run driver RedefineSharedClassJFR xshare-off
35+
* @run driver RedefineSharedClassJFR xshare-on
36+
*/
37+
import java.util.ArrayList;
38+
import java.util.List;
39+
40+
import jdk.test.lib.Platform;
41+
import jdk.test.lib.process.ProcessTools;
42+
import jdk.test.lib.process.OutputAnalyzer;
43+
44+
import jtreg.SkippedException;
45+
46+
public class RedefineSharedClassJFR {
47+
48+
private static final String SHOULD_CLEAN_TRUE = "Class unloading: should_clean_previous_versions = true";
49+
private static final String SHOULD_CLEAN_FALSE = "Class unloading: should_clean_previous_versions = false";
50+
private static final String SCRATCH_CLASS_ADDED_SHARED = "scratch class added; class is shared";
51+
private static final String SCRATCH_CLASS_ADDED_ON_STACK = "scratch class added; one of its methods is on_stack.";
52+
53+
public static void main(String[] args) throws Exception {
54+
// Skip test if default archive is supported.
55+
if (!Platform.isDefaultCDSArchiveSupported()) {
56+
throw new SkippedException("Supported platform");
57+
}
58+
59+
// Test is run with JFR which will transform a number of classes. Depending
60+
// on if the test is run with or without CDS the output will be different,
61+
// due to the fact that shared classes can never be cleaned out after retranform.
62+
if (args.length > 0) {
63+
// When run with an argument the class is used as driver and should parse
64+
// the output to verify it is correct given the command line.
65+
List<String> baseCommand = List.of(
66+
"-XX:StartFlightRecording",
67+
"-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
68+
"RedefineSharedClassJFR");
69+
70+
if (args[0].equals("xshare-off")) {
71+
// First case is with -Xshare:off. In this case no classes are shared
72+
// and we should be able to clean out the retransformed classes. There
73+
// is no guarantee that any classes will be in use, so just verify that
74+
// no classes are added due to being shared.
75+
List<String> offCommand = new ArrayList<>();
76+
offCommand.add("-Xshare:off");
77+
offCommand.addAll(baseCommand);
78+
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(offCommand);
79+
new OutputAnalyzer(pb.start())
80+
// We can't expect any of the transformed classes to be in use
81+
// so the only thing we can verify is that no scratch classes
82+
// are added because they are shared.
83+
.shouldNotContain(SCRATCH_CLASS_ADDED_SHARED)
84+
.shouldHaveExitValue(0);
85+
return;
86+
} else if (args[0].equals("xshare-on")) {
87+
// With -Xshare:on, the shared classes can never be cleaned out. Check the
88+
// logs to verify we don't try to clean when we know it is not needed.
89+
List<String> onCommand = new ArrayList<>();
90+
onCommand.add("-Xshare:on");
91+
onCommand.addAll(baseCommand);
92+
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(onCommand);
93+
new OutputAnalyzer(pb.start())
94+
.shouldContain(SHOULD_CLEAN_FALSE)
95+
.shouldNotContain(SHOULD_CLEAN_TRUE)
96+
.shouldContain(SCRATCH_CLASS_ADDED_SHARED)
97+
// If the below line occurs, then should_clean_previous_versions will be
98+
// true and the above shouldContain will trigger. This check is to
99+
// show the intention that we don't expect any non-shared transformed
100+
// classes to be in use.
101+
.shouldNotContain(SCRATCH_CLASS_ADDED_ON_STACK)
102+
.shouldHaveExitValue(0);
103+
return;
104+
}
105+
}
106+
107+
// When run without any argument this class acts as test and we do a system GC
108+
// to trigger cleaning and get the output we want to check.
109+
System.gc();
110+
}
111+
}

0 commit comments

Comments
 (0)