< prev index next >

test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java

Print this page

        

*** 23,145 **** /* * @test * @bug 8174749 8213307 * @summary MemberNameTable should reuse entries ! * @library /test/lib /runtime/testlibrary ! * @modules java.base/jdk.internal.misc ! * @modules java.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MemberNameLeak */ import java.lang.invoke.*; - import java.lang.reflect.*; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import sun.hotspot.WhiteBox; import sun.hotspot.code.Compiler; import sun.hotspot.gc.GC; public class MemberNameLeak { - private static String className = "MemberNameLeakTestClass"; - private static String methodPrefix = "method"; - // The size of the ResolvedMethodTable is 1024. 2000 entries - // is enough to trigger a grow/cleaning of the table after a GC. - private static int methodCount = 2000; - static class Leak { public void callMe() { } public static void main(String[] args) throws Throwable { Leak leak = new Leak(); WhiteBox wb = WhiteBox.getWhiteBox(); ! ClassWithManyMethodsClassLoader classLoader = new ClassWithManyMethodsClassLoader(); ! Class<?> clazz = classLoader.create(className, methodPrefix, methodCount); ! ! long before = wb.resolvedMethodItemsCount(); ! ! Object o = clazz.newInstance(); ! MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup()); ! ! for (int i = 0; i < methodCount; i++) { ! MethodType mt = MethodType.fromMethodDescriptorString("()V", classLoader); ! String methodName = methodPrefix + i; // findSpecial leaks some native mem ! // Add entry to ResolvedMethodTable. ! MethodHandle mh0 = lookup.findSpecial(clazz, methodName, mt, clazz); ! // Find entry in ResolvedMethodTable. ! MethodHandle mh1 = lookup.findSpecial(clazz, methodName, mt, clazz); ! ! mh1.invoke(o); ! } ! ! long after = wb.resolvedMethodItemsCount(); ! ! if (after == before) { ! throw new RuntimeException("Too few resolved methods"); } // Wait until ServiceThread cleans ResolvedMethod table int cnt = 0; while (true) { if (cnt++ % 30 == 0) { System.gc(); // make mh unused } ! ! if (after != wb.resolvedMethodItemsCount()) { ! // Entries have been removed. break; } - Thread.sleep(100); } } } ! public static void test(GC gc, boolean doConcurrent) throws Throwable { ! System.err.println("test(" + gc + ", " + doConcurrent + ")"); // Run this Leak class with logging ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-Xlog:membername+table=trace", "-XX:+UnlockExperimentalVMOptions", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "-Xbootclasspath/a:.", doConcurrent ? "-XX:+ExplicitGCInvokesConcurrent" : "-XX:-ExplicitGCInvokesConcurrent", "-XX:+ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", ! "-XX:+Use" + gc + "GC", ! Leak.class.getName()); OutputAnalyzer output = new OutputAnalyzer(pb.start()); ! // Hardcoded names for classes generated by GeneratedClassLoader ! String descriptor = className + "." + methodPrefix + "0()V"; ! output.shouldContain("ResolvedMethod entry added for " + descriptor); ! output.shouldContain("ResolvedMethod entry found for " + descriptor); output.shouldContain("ResolvedMethod entry removed"); output.shouldHaveExitValue(0); } ! private static boolean supportsSTW(GC gc) { ! return !(gc == GC.Epsilon); ! } ! ! private static boolean supportsConcurrent(GC gc) { ! return !(gc == GC.Epsilon || gc == GC.Serial || gc == GC.Parallel); ! } ! private static void test(GC gc) throws Throwable { ! if (supportsSTW(gc)) { ! test(gc, false); } - if (supportsConcurrent(gc)) { - test(gc, true); - } - } - - public static void main(java.lang.String[] unused) throws Throwable { - test(GC.selected()); } } --- 23,110 ---- /* * @test * @bug 8174749 8213307 * @summary MemberNameTable should reuse entries ! * @requires vm.gc == "null" ! * @library /test/lib * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MemberNameLeak */ import java.lang.invoke.*; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import sun.hotspot.WhiteBox; import sun.hotspot.code.Compiler; import sun.hotspot.gc.GC; public class MemberNameLeak { static class Leak { public void callMe() { } public static void main(String[] args) throws Throwable { Leak leak = new Leak(); WhiteBox wb = WhiteBox.getWhiteBox(); + int removedCountOrig = wb.resolvedMethodRemovedCount(); + int removedCount; ! for (int i = 0; i < 10; i++) { ! MethodHandles.Lookup lookup = MethodHandles.lookup(); ! MethodType mt = MethodType.fromMethodDescriptorString("()V", Leak.class.getClassLoader()); // findSpecial leaks some native mem ! MethodHandle mh = lookup.findSpecial(Leak.class, "callMe", mt, Leak.class); ! mh.invokeExact(leak); } // Wait until ServiceThread cleans ResolvedMethod table int cnt = 0; while (true) { if (cnt++ % 30 == 0) { System.gc(); // make mh unused } ! removedCount = wb.resolvedMethodRemovedCount(); ! if (removedCountOrig != removedCount) { break; } Thread.sleep(100); } } } ! public static void test(String gc, boolean doConcurrent) throws Throwable { // Run this Leak class with logging ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-Xlog:membername+table=trace", "-XX:+UnlockExperimentalVMOptions", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "-Xbootclasspath/a:.", doConcurrent ? "-XX:+ExplicitGCInvokesConcurrent" : "-XX:-ExplicitGCInvokesConcurrent", "-XX:+ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", ! gc, Leak.class.getName()); OutputAnalyzer output = new OutputAnalyzer(pb.start()); ! output.shouldContain("ResolvedMethod entry added for MemberNameLeak$Leak.callMe()V"); ! output.shouldContain("ResolvedMethod entry found for MemberNameLeak$Leak.callMe()V"); output.shouldContain("ResolvedMethod entry removed"); output.shouldHaveExitValue(0); } ! public static void main(java.lang.String[] unused) throws Throwable { ! test("-XX:+UseG1GC", false); ! test("-XX:+UseG1GC", true); ! test("-XX:+UseParallelGC", false); ! test("-XX:+UseSerialGC", false); ! if (!Compiler.isGraalEnabled()) { // Graal does not support CMS ! test("-XX:+UseConcMarkSweepGC", false); ! test("-XX:+UseConcMarkSweepGC", true); ! if (GC.Shenandoah.isSupported()) { ! test("-XX:+UseShenandoahGC", true); ! test("-XX:+UseShenandoahGC", false); ! } } } }
< prev index next >