Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/test/gc/shenandoah/oom/TestClassLoaderLeak.java
32285 views
1
/*
2
* Copyright (c) 2018, Red Hat, Inc. All rights reserved.
3
*
4
* This code is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 2 only, as
6
* published by the Free Software Foundation.
7
*
8
* This code is distributed in the hope that it will be useful, but WITHOUT
9
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11
* version 2 for more details (a copy is included in the LICENSE file that
12
* accompanied this code).
13
*
14
* You should have received a copy of the GNU General Public License version
15
* 2 along with this work; if not, write to the Free Software Foundation,
16
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*
18
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19
* or visit www.oracle.com if you need additional information or have any
20
* questions.
21
*
22
*/
23
24
/**
25
* @test TestClassLoaderLeak
26
* @summary Test OOME in due to classloader leak
27
* @key gc
28
* @library /testlibrary
29
*
30
* @run main/timeout=480 TestClassLoaderLeak
31
*/
32
33
import java.util.*;
34
import java.io.*;
35
import java.nio.*;
36
import java.nio.file.*;
37
import com.oracle.java.testlibrary.*;
38
39
public class TestClassLoaderLeak {
40
41
static final int SIZE = 1 * 1024 * 1024;
42
static final int COUNT = 128;
43
44
static volatile Object sink;
45
46
static class Dummy {
47
static final int[] PAYLOAD = new int[SIZE];
48
}
49
50
static class MyClassLoader extends ClassLoader {
51
final String path;
52
53
MyClassLoader(String path) {
54
this.path = path;
55
}
56
57
public Class<?> loadClass(String name) throws ClassNotFoundException {
58
try {
59
File f = new File(path, name + ".class");
60
if (!f.exists()) {
61
return super.loadClass(name);
62
}
63
64
Path path = Paths.get(f.getAbsolutePath());
65
byte[] cls = Files.readAllBytes(path);
66
return defineClass(name, cls, 0, cls.length, null);
67
} catch (IOException e) {
68
throw new ClassNotFoundException(name);
69
}
70
}
71
}
72
73
static void load(String path) throws Exception {
74
ClassLoader cl = new MyClassLoader(path);
75
Class<Dummy> c = (Class<Dummy>) Class.forName("TestClassLoaderLeak$Dummy", true, cl);
76
if (c.getClassLoader() != cl) {
77
throw new IllegalStateException("Should have loaded by target loader");
78
}
79
sink = c;
80
}
81
82
public static void passWith(String... args) throws Exception {
83
testWith(true, args);
84
}
85
86
public static void failWith(String... args) throws Exception {
87
testWith(false, args);
88
}
89
90
public static void testWith(boolean shouldPass, String... args) throws Exception {
91
List<String> pbArgs = new ArrayList<>();
92
pbArgs.add("-Xmx128m");
93
pbArgs.add("-XX:+UnlockExperimentalVMOptions");
94
pbArgs.add("-XX:+UnlockDiagnosticVMOptions");
95
pbArgs.add("-XX:+UseShenandoahGC");
96
pbArgs.addAll(Arrays.asList(args));
97
pbArgs.add(TestClassLoaderLeak.class.getName());
98
pbArgs.add("test");
99
100
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(pbArgs.toArray(new String[0]));
101
102
OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
103
104
if (shouldPass) {
105
analyzer.shouldHaveExitValue(0);
106
analyzer.shouldNotContain("java.lang.OutOfMemoryError");
107
analyzer.shouldContain("All good");
108
} else {
109
analyzer.shouldHaveExitValue(1);
110
analyzer.shouldContain("java.lang.OutOfMemoryError");
111
analyzer.shouldNotContain("All good");
112
}
113
}
114
115
public static void main(String[] args) throws Exception {
116
if (args.length > 0) {
117
String classDir = TestClassLoaderLeak.class.getProtectionDomain().getCodeSource().getLocation().getPath();
118
for (int c = 0; c < COUNT; c++) {
119
load(classDir);
120
}
121
System.out.println("All good");
122
return;
123
}
124
125
String[][][] modeHeuristics = new String[][][] {
126
{{"satb"}, {"adaptive", "compact", "static", "aggressive"}},
127
{{"iu"}, {"adaptive", "aggressive"}},
128
{{"passive"}, {"passive"}}
129
};
130
131
for (String[][] mh : modeHeuristics) {
132
String mode = mh[0][0];
133
String[] heuristics = mh[1];
134
for (String h : heuristics) {
135
// Forceful enabling should work
136
passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading");
137
passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloadingWithConcurrentMark");
138
139
// Even when concurrent unloading is disabled, Full GC has to recover
140
passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark");
141
passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=0");
142
passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=0");
143
144
// Should OOME when unloading forcefully disabled, even if local flags try to enable it back
145
failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading");
146
failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark");
147
failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=1");
148
failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=1");
149
}
150
}
151
}
152
}
153
154