< prev index next >

test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderStatsTest.java

Print this page
rev 58565 : 8238358: Implementation of JEP 371: Hidden Classes
Reviewed-by: duke
Contributed-by: mandy.chung@oracle.com, lois.foltan@oracle.com, david.holmes@oracle.com, harold.seigel@oracle.com, serguei.spitsyn@oracle.com, alex.buckley@oracle.com, jamsheed.c.m@oracle.com
rev 58568 : [mq]: hidden-class-4

*** 1,7 **** /* ! * Copyright (c) 2014, 2017, 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. --- 1,7 ---- /* ! * Copyright (c) 2014, 2020, 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.
*** 27,77 **** * @library /test/lib * @modules java.base/jdk.internal.misc * java.compiler * java.management * jdk.internal.jvmstat/sun.jvmstat.monitor ! * @run testng ClassLoaderStatsTest */ import org.testng.annotations.Test; import org.testng.Assert; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.dcmd.CommandExecutor; import jdk.test.lib.dcmd.JMXExecutor; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ClassLoaderStatsTest { // ClassLoader Parent CLD* Classes ChunkSz BlockSz Type ! // 0x00000007c0215928 0x0000000000000000 0x0000000000000000 0 0 0 org.eclipse.osgi.baseadaptor.BaseAdaptor$1 ! // 0x00000007c0009868 0x0000000000000000 0x00007fc52aebcc80 1 6144 3768 sun.reflect.DelegatingClassLoader ! // 0x00000007c0009868 0x0000000000000000 0x00007fc52b8916d0 1 6144 3688 sun.reflect.DelegatingClassLoader ! // 0x00000007c0009868 0x00000007c0038ba8 0x00007fc52afb8760 1 6144 3688 sun.reflect.DelegatingClassLoader ! // 0x00000007c0009868 0x0000000000000000 0x00007fc52afbb1a0 1 6144 3688 sun.reflect.DelegatingClassLoader ! // 0x0000000000000000 0x0000000000000000 0x00007fc523416070 5019 30060544 29956216 <boot classloader> ! // 455 1210368 672848 + unsafe anonymous classes ! // 0x00000007c016b5c8 0x00000007c0038ba8 0x00007fc52a995000 5 8192 5864 org.netbeans.StandardModule$OneModuleClassLoader ! // 0x00000007c0009868 0x00000007c016b5c8 0x00007fc52ac13640 1 6144 3896 sun.reflect.DelegatingClassLoader // ... static Pattern clLine = Pattern.compile("0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*(.*)"); static Pattern anonLine = Pattern.compile("\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*.*"); public static DummyClassLoader dummyloader; public void run(CommandExecutor executor) throws ClassNotFoundException { ! // create a classloader and load our special class dummyloader = new DummyClassLoader(); Class<?> c = Class.forName("TestClass", true, dummyloader); if (c.getClassLoader() != dummyloader) { Assert.fail("TestClass defined by wrong classloader: " + c.getClassLoader()); } --- 27,84 ---- * @library /test/lib * @modules java.base/jdk.internal.misc * java.compiler * java.management * jdk.internal.jvmstat/sun.jvmstat.monitor ! * @run testng/othervm --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED ClassLoaderStatsTest */ import org.testng.annotations.Test; import org.testng.Assert; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.dcmd.CommandExecutor; import jdk.test.lib.dcmd.JMXExecutor; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; + import java.lang.invoke.MethodHandles; + import java.lang.invoke.MethodHandles.Lookup; + import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; + import java.nio.file.Path; + import java.nio.file.Paths; import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; + import jdk.internal.misc.Unsafe; + public class ClassLoaderStatsTest { + // Expected output from VM.classloader_stats: // ClassLoader Parent CLD* Classes ChunkSz BlockSz Type ! // 0x0000000800bd3830 0x000000080037f468 0x00007f001c2ea170 1 10240 4672 ClassLoaderStatsTest$DummyClassLoader ! // 1 2048 1080 + unsafe anonymous classes ! // 1 2048 1088 + hidden classes ! // 0x0000000000000000 0x0000000000000000 0x00007f00e852d190 1607 4628480 3931216 <boot class loader> ! // 38 124928 85856 + hidden classes ! // 0x00000008003b5508 0x0000000000000000 0x00007f001c2d4760 1 6144 4040 jdk.internal.reflect.DelegatingClassLoader ! // 0x000000080037f468 0x000000080037ee80 0x00007f00e868e3f0 228 1368064 1286672 jdk.internal.loader.ClassLoaders$AppClassLoader // ... static Pattern clLine = Pattern.compile("0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*(.*)"); static Pattern anonLine = Pattern.compile("\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*.*"); public static DummyClassLoader dummyloader; public void run(CommandExecutor executor) throws ClassNotFoundException { ! // create a classloader and load our special classes dummyloader = new DummyClassLoader(); Class<?> c = Class.forName("TestClass", true, dummyloader); if (c.getClassLoader() != dummyloader) { Assert.fail("TestClass defined by wrong classloader: " + c.getClassLoader()); }
*** 80,107 **** Iterator<String> lines = output.asLines().iterator(); while (lines.hasNext()) { String line = lines.next(); Matcher m = clLine.matcher(line); if (m.matches()) { ! // verify that DummyClassLoader has loaded 1 class and 1 anonymous class if (m.group(4).equals("ClassLoaderStatsTest$DummyClassLoader")) { ! System.out.println("line: " + line); if (!m.group(1).equals("1")) { Assert.fail("Should have loaded 1 class: " + line); } checkPositiveInt(m.group(2)); checkPositiveInt(m.group(3)); String next = lines.next(); ! System.out.println("next: " + next); Matcher m1 = anonLine.matcher(next); m1.matches(); if (!m1.group(1).equals("1")) { Assert.fail("Should have loaded 1 anonymous class, but found : " + m1.group(1)); } checkPositiveInt(m1.group(2)); checkPositiveInt(m1.group(3)); } } } } --- 87,130 ---- Iterator<String> lines = output.asLines().iterator(); while (lines.hasNext()) { String line = lines.next(); Matcher m = clLine.matcher(line); if (m.matches()) { ! // verify that DummyClassLoader has loaded 1 class, 1 anonymous class, and 1 hidden class if (m.group(4).equals("ClassLoaderStatsTest$DummyClassLoader")) { ! System.out.println("DummyClassLoader line: " + line); if (!m.group(1).equals("1")) { Assert.fail("Should have loaded 1 class: " + line); } checkPositiveInt(m.group(2)); checkPositiveInt(m.group(3)); String next = lines.next(); ! System.out.println("DummyClassLoader next: " + next); ! if (!next.contains("unsafe anonymous classes")) { ! Assert.fail("Should have an anonymous class"); ! } Matcher m1 = anonLine.matcher(next); m1.matches(); if (!m1.group(1).equals("1")) { Assert.fail("Should have loaded 1 anonymous class, but found : " + m1.group(1)); } checkPositiveInt(m1.group(2)); checkPositiveInt(m1.group(3)); + + next = lines.next(); + System.out.println("DummyClassLoader next: " + next); + if (!next.contains("hidden classes")) { + Assert.fail("Should have a hidden class"); + } + Matcher m2 = anonLine.matcher(next); + m2.matches(); + if (!m2.group(1).equals("1")) { + Assert.fail("Should have loaded 1 hidden class, but found : " + m2.group(1)); + } + checkPositiveInt(m2.group(2)); + checkPositiveInt(m2.group(3)); } } } }
*** 115,126 **** public static final String CLASS_NAME = "TestClass"; static ByteBuffer readClassFile(String name) { ! File f = new File(System.getProperty("test.classes", "."), ! name); try (FileInputStream fin = new FileInputStream(f); FileChannel fc = fin.getChannel()) { return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); } catch (IOException e) { --- 138,148 ---- public static final String CLASS_NAME = "TestClass"; static ByteBuffer readClassFile(String name) { ! File f = new File(System.getProperty("test.classes", "."), name); try (FileInputStream fin = new FileInputStream(f); FileChannel fc = fin.getChannel()) { return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); } catch (IOException e) {
*** 161,172 **** public void jmx() throws ClassNotFoundException { run(new JMXExecutor()); } } class TestClass { static { ! // force creation of anonymous class (for the lambdaform) ! Runnable r = () -> System.out.println("Hello"); ! r.run(); } } --- 183,225 ---- public void jmx() throws ClassNotFoundException { run(new JMXExecutor()); } } + class HiddenClass { } + class TestClass { + private static final String HCName = "HiddenClass.class"; + private static final String DIR = System.getProperty("test.classes"); + static Unsafe unsafe = Unsafe.getUnsafe(); + static { ! try { ! // Create a hidden non-strong class and an anonymous class. ! byte[] klassBuf = readClassFile(DIR + File.separator + HCName); ! Class<?> hc = defineHiddenClass(klassBuf); ! Class ac = unsafe.defineAnonymousClass(TestClass.class, klassBuf, new Object[0]); ! } catch (Throwable e) { ! throw new RuntimeException("Unexpected exception in TestClass: " + e.getMessage()); ! } ! } ! ! ! static byte[] readClassFile(String classFileName) throws Exception { ! File classFile = new File(classFileName); ! try (FileInputStream in = new FileInputStream(classFile); ! ByteArrayOutputStream out = new ByteArrayOutputStream()) ! { ! int b; ! while ((b = in.read()) != -1) { ! out.write(b); ! } ! return out.toByteArray(); ! } ! } ! ! static Class<?> defineHiddenClass(byte[] bytes) throws Exception { ! Lookup lookup = MethodHandles.lookup(); ! Class<?> hc = lookup.defineHiddenClass(bytes, false, NESTMATE).lookupClass(); ! return hc; } }
< prev index next >