diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 71c015cad5bd..778cfd815ae0 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1251,6 +1251,9 @@ void CodeCache::report_codemem_full(int code_blob_type, bool print) { warning("%s", msg1); warning("%s", msg2); } + + heap->report_full(); + ResourceMark rm; stringStream s; // Dump code cache into a buffer before locking the tty. @@ -1270,8 +1273,6 @@ void CodeCache::report_codemem_full(int code_blob_type, bool print) { } } - heap->report_full(); - EventCodeCacheFull event; if (event.should_commit()) { event.set_codeBlobType((u1)code_blob_type); diff --git a/test/hotspot/jtreg/compiler/codecache/CodeCacheFullCountTest.java b/test/hotspot/jtreg/compiler/codecache/CodeCacheFullCountTest.java new file mode 100644 index 000000000000..2bda5d706e91 --- /dev/null +++ b/test/hotspot/jtreg/compiler/codecache/CodeCacheFullCountTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.URL; +import java.net.URLClassLoader; +import java.lang.reflect.Field; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/* + * @test + * @bug 8276036 + * @summary test for the value of full_count in the message of insufficient codecache + * @library /test/lib + */ +public class CodeCacheFullCountTest { + public static void main(String args[]) throws Throwable { + if (args.length == 1) { + wasteCodeCache(); + } else { + runtest(); + } + } + + public static void wasteCodeCache() throws Exception { + URL url = CodeCacheFullCountTest.class.getProtectionDomain().getCodeSource().getLocation(); + + for (int i = 0; i < 500; i++) { + ClassLoader cl = new MyClassLoader(url); + refClass(cl.loadClass("SomeClass")); + } + } + + public static void runtest() throws Throwable { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:ReservedCodeCacheSize=2496k", "-XX:-UseCodeCacheFlushing", "CodeCacheFullCountTest", "WasteCodeCache"); + Process javaProcess = pb.start(); + javaProcess.waitFor(); + + OutputAnalyzer javaOutput = new OutputAnalyzer(javaProcess); + String stdout = javaOutput.getStdout(); + System.out.println(stdout); + + Pattern pattern = Pattern.compile("full_count=(\\d)"); + Matcher stdoutMatcher = pattern.matcher(stdout); + if (stdoutMatcher.find()) { + int fullCount = Integer.parseInt(stdoutMatcher.group(1)); + if (fullCount != 1) { + throw new RuntimeException("the value of full_count is wrong."); + } + } else { + throw new RuntimeException("codecache shortage was not occured."); + } + } + + private static void refClass(Class clazz) throws Exception { + Field name = clazz.getDeclaredField("NAME"); + name.setAccessible(true); + name.get(null); + } + + private static class MyClassLoader extends URLClassLoader { + public MyClassLoader(URL url) { + super(new URL[]{url}, null); + } + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + try { + return super.loadClass(name, resolve); + } catch (ClassNotFoundException e) { + return Class.forName(name, resolve, CodeCacheFullCountTest.class.getClassLoader()); + } + } + } +} + +abstract class Foo { + public abstract int foo(); +} +class Foo1 extends Foo { + private int a; + public int foo() { return a; } +} +class Foo2 extends Foo { + private int a; + public int foo() { return a; } +} +class Foo3 extends Foo { + private int a; + public int foo() { return a; } +} +class Foo4 extends Foo { + private int a; + public int foo() { return a; } +} + +class SomeClass { + static final String NAME = "name"; + + static { + int res =0; + Foo[] foos = new Foo[] { new Foo1(), new Foo2(), new Foo3(), new Foo4() }; + for (int i = 0; i < 100000; i++) { + res = foos[i % foos.length].foo(); + } + } +}