Path: blob/master/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java
41153 views
/*1* Copyright (c) 2018, Red Hat, Inc. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 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 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324/**25* @test TestClassLoaderLeak26* @summary Test OOME in due to classloader leak27* @requires vm.gc.Shenandoah28* @library /test/lib29* @run driver TestClassLoaderLeak30*/3132import java.util.*;33import java.io.*;34import java.nio.*;35import java.nio.file.*;3637import jdk.test.lib.process.OutputAnalyzer;38import jdk.test.lib.process.ProcessTools;3940public class TestClassLoaderLeak {4142static final int SIZE = 1 * 1024 * 1024;43static final int COUNT = 128;4445static volatile Object sink;4647static class Dummy {48static final int[] PAYLOAD = new int[SIZE];49}5051static class MyClassLoader extends ClassLoader {52final String path;5354MyClassLoader(String path) {55this.path = path;56}5758public Class<?> loadClass(String name) throws ClassNotFoundException {59try {60File f = new File(path, name + ".class");61if (!f.exists()) {62return super.loadClass(name);63}6465Path path = Paths.get(f.getAbsolutePath());66byte[] cls = Files.readAllBytes(path);67return defineClass(name, cls, 0, cls.length, null);68} catch (IOException e) {69throw new ClassNotFoundException(name);70}71}72}7374static void load(String path) throws Exception {75ClassLoader cl = new MyClassLoader(path);76Class<Dummy> c = (Class<Dummy>) Class.forName("TestClassLoaderLeak$Dummy", true, cl);77if (c.getClassLoader() != cl) {78throw new IllegalStateException("Should have loaded by target loader");79}80sink = c;81}8283public static void passWith(String... args) throws Exception {84testWith(true, args);85}8687public static void failWith(String... args) throws Exception {88testWith(false, args);89}9091public static void testWith(boolean shouldPass, String... args) throws Exception {92List<String> pbArgs = new ArrayList<>();93pbArgs.add("-Xmx128m");94pbArgs.add("-XX:+UnlockExperimentalVMOptions");95pbArgs.add("-XX:+UnlockDiagnosticVMOptions");96pbArgs.add("-XX:+UseShenandoahGC");97pbArgs.addAll(Arrays.asList(args));98pbArgs.add(TestClassLoaderLeak.class.getName());99pbArgs.add("test");100101ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(pbArgs.toArray(new String[0]));102103OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());104105if (shouldPass) {106analyzer.shouldHaveExitValue(0);107analyzer.shouldNotContain("java.lang.OutOfMemoryError");108analyzer.shouldContain("All good");109} else {110analyzer.shouldHaveExitValue(1);111analyzer.shouldContain("java.lang.OutOfMemoryError");112analyzer.shouldNotContain("All good");113}114}115116public static void main(String[] args) throws Exception {117if (args.length > 0) {118String classDir = TestClassLoaderLeak.class.getProtectionDomain().getCodeSource().getLocation().getPath();119for (int c = 0; c < COUNT; c++) {120load(classDir);121}122System.out.println("All good");123return;124}125126String[][][] modeHeuristics = new String[][][] {127{{"satb"}, {"adaptive", "compact", "static", "aggressive"}},128{{"iu"}, {"adaptive", "aggressive"}},129{{"passive"}, {"passive"}}130};131132for (String[][] mh : modeHeuristics) {133String mode = mh[0][0];134String[] heuristics = mh[1];135for (String h : heuristics) {136// Forceful enabling should work137passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading");138passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloadingWithConcurrentMark");139140// Even when concurrent unloading is disabled, Full GC has to recover141passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark");142passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=0");143passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=0");144145// Should OOME when unloading forcefully disabled, even if local flags try to enable it back146failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading");147failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark");148failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=1");149failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=1");150}151}152}153}154155156