1 /* 2 * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.jfr.event.runtime; 27 28 import java.io.File; 29 import java.io.FileInputStream; 30 import java.io.IOException; 31 import java.lang.reflect.Method; 32 import java.nio.ByteBuffer; 33 import java.nio.channels.FileChannel; 34 import java.util.List; 35 36 import jdk.jfr.Recording; 37 import jdk.jfr.consumer.RecordedClassLoader; 38 import jdk.jfr.consumer.RecordedEvent; 39 import jdk.test.lib.Asserts; 40 import jdk.test.lib.jfr.EventNames; 41 import jdk.test.lib.jfr.Events; 42 43 import jdk.test.lib.compiler.InMemoryJavaCompiler; 44 45 /** 46 * @test 47 * @key jfr 48 * @requires vm.hasJFR 49 * @library /test/lib /test/jdk 50 * @modules java.base/jdk.internal.misc 51 * java.compiler 52 * @build jdk.jfr.event.runtime.TestClasses 53 * @run main/othervm jdk.jfr.event.runtime.TestClassLoaderStatsEvent 54 */ 55 public class TestClassLoaderStatsEvent { 56 private final static String EVENT_NAME = EventNames.ClassLoaderStatistics; 57 private final static String CLASS_LOADER_NAME = "MyDummyClassLoader"; 58 private final static String CLASSLOADER_TYPE_NAME = "jdk.jfr.event.runtime.TestClassLoaderStatsEvent$DummyClassLoader"; 59 public static DummyClassLoader dummyloader; 60 61 public static void main(String[] args) throws Throwable { 62 createDummyClassLoader(CLASS_LOADER_NAME); 63 64 Recording recording = new Recording(); 65 recording.enable(EVENT_NAME); 66 recording.start(); 67 recording.stop(); 68 List<RecordedEvent> consumer = Events.fromRecording(recording); 69 Events.hasEvents(consumer); 70 71 boolean isAnyFound = false; 72 for (RecordedEvent event : consumer) { 73 System.out.println("Event:" + event); 74 if (Events.assertField(event, "classLoader").getValue() == null) { 75 continue; 76 } 77 RecordedClassLoader recordedClassLoader = event.getValue("classLoader"); 78 if (CLASSLOADER_TYPE_NAME.equals(recordedClassLoader.getType().getName())) { 79 Asserts.assertEquals(CLASS_LOADER_NAME, recordedClassLoader.getName(), 80 "Expected class loader name " + CLASS_LOADER_NAME + ", got name " + recordedClassLoader.getName()); 81 Events.assertField(event, "classCount").equal(2L); 82 Events.assertField(event, "chunkSize").above(1L); 83 Events.assertField(event, "blockSize").above(1L); 84 Events.assertField(event, "unsafeAnonymousClassCount").equal(2L); 85 Events.assertField(event, "unsafeAnonymousChunkSize").above(0L); 86 Events.assertField(event, "unsafeAnonymousBlockSize").above(0L); 87 Events.assertField(event, "hiddenClassCount").equal(2L); 88 Events.assertField(event, "hiddenChunkSize").above(0L); 89 Events.assertField(event, "hiddenBlockSize").above(0L); 90 isAnyFound = true; 91 } 92 } 93 Asserts.assertTrue(isAnyFound, "No events found"); 94 } 95 96 private static void createDummyClassLoader(String name) throws Throwable { 97 dummyloader = new DummyClassLoader(name); 98 Class<?> c = Class.forName(TestClass.class.getName(), true, dummyloader); 99 if (c.getClassLoader() != dummyloader) { 100 throw new RuntimeException("TestClass defined by wrong classloader: " + c.getClassLoader()); 101 } 102 103 // Compile a class for method createNonFindableClasses() to use to create both a 104 // weak hidden class and an anonymous class. 105 byte klassbuf[] = InMemoryJavaCompiler.compile("jdk.jfr.event.runtime.TestClass", 106 "package jdk.jfr.event.runtime; " + 107 "public class TestClass { " + 108 " public static void concat(String one, String two) throws Throwable { " + 109 " } } "); 110 111 Method m = c.getDeclaredMethod("createNonFindableClasses", byte[].class); 112 m.setAccessible(true); 113 m.invoke(null, klassbuf); 114 } 115 116 public static class DummyClassLoader extends ClassLoader { 117 118 static ByteBuffer readClassFile(String name) { 119 String testClasses = System.getProperty("test.classes"); 120 File f = new File(testClasses, name); 121 try (FileInputStream fin = new FileInputStream(f)) { 122 FileChannel fc = fin.getChannel(); 123 return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); 124 } catch (IOException e) { 125 throw new RuntimeException("Can't open file: " + f, e); 126 } 127 } 128 129 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 130 Class<?> c; 131 if (TestClass.class.getName().equals(name)) { 132 c = findClass(name); 133 if (resolve) { 134 resolveClass(c); 135 } 136 } else { 137 c = super.loadClass(name, resolve); 138 } 139 return c; 140 } 141 142 protected Class<?> findClass(String name) throws ClassNotFoundException { 143 if (!TestClass.class.getName().equals(name)) { 144 throw new ClassNotFoundException("Unexpected class: " + name); 145 } 146 return defineClass(name, readClassFile(TestClass.class.getName().replace(".", File.separator) + ".class"), null); 147 } 148 149 public DummyClassLoader(String name) { 150 super(name, ClassLoader.getSystemClassLoader()); 151 } 152 } 153 }