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 * jdk.compiler 52 * jdk.jfr 53 * @build jdk.jfr.event.runtime.TestClasses 54 * @run main/othervm jdk.jfr.event.runtime.TestClassLoaderStatsEvent 55 */ 56 public class TestClassLoaderStatsEvent { 57 private final static String EVENT_NAME = EventNames.ClassLoaderStatistics; 58 private final static String CLASS_LOADER_NAME = "MyDummyClassLoader"; 59 private final static String CLASSLOADER_TYPE_NAME = "jdk.jfr.event.runtime.TestClassLoaderStatsEvent$DummyClassLoader"; 60 public static DummyClassLoader dummyloader; 61 62 public static void main(String[] args) throws Throwable { 63 createDummyClassLoader(CLASS_LOADER_NAME); 64 65 Recording recording = new Recording(); 66 recording.enable(EVENT_NAME); 67 recording.start(); 68 recording.stop(); 69 List<RecordedEvent> consumer = Events.fromRecording(recording); 70 Events.hasEvents(consumer); 71 72 boolean isAnyFound = false; 73 for (RecordedEvent event : consumer) { 74 System.out.println("Event:" + event); 75 if (Events.assertField(event, "classLoader").getValue() == null) { 76 continue; 77 } 78 RecordedClassLoader recordedClassLoader = event.getValue("classLoader"); 79 if (CLASSLOADER_TYPE_NAME.equals(recordedClassLoader.getType().getName())) { 80 Asserts.assertEquals(CLASS_LOADER_NAME, recordedClassLoader.getName(), 81 "Expected class loader name " + CLASS_LOADER_NAME + ", got name " + recordedClassLoader.getName()); 82 Events.assertField(event, "classCount").equal(2L); 83 Events.assertField(event, "chunkSize").above(1L); 84 Events.assertField(event, "blockSize").above(1L); 85 Events.assertField(event, "unsafeAnonymousClassCount").equal(2L); 86 Events.assertField(event, "unsafeAnonymousChunkSize").above(0L); 87 Events.assertField(event, "unsafeAnonymousBlockSize").above(0L); 88 Events.assertField(event, "hiddenClassCount").equal(2L); 89 Events.assertField(event, "hiddenChunkSize").above(0L); 90 Events.assertField(event, "hiddenBlockSize").above(0L); 91 isAnyFound = true; 92 } 93 } 94 Asserts.assertTrue(isAnyFound, "No events found"); 95 } 96 97 private static void createDummyClassLoader(String name) throws Throwable { 98 dummyloader = new DummyClassLoader(name); 99 Class<?> c = Class.forName(TestClass.class.getName(), true, dummyloader); 100 if (c.getClassLoader() != dummyloader) { 101 throw new RuntimeException("TestClass defined by wrong classloader: " + c.getClassLoader()); 102 } 103 104 // Compile a class for method createNonFindableClasses() to use to create both a 105 // weak hidden class and an anonymous class. 106 byte klassbuf[] = InMemoryJavaCompiler.compile("jdk.jfr.event.runtime.TestClass", 107 "package jdk.jfr.event.runtime; " + 108 "public class TestClass { " + 109 " public static void concat(String one, String two) throws Throwable { " + 110 " } } "); 111 112 Method m = c.getDeclaredMethod("createNonFindableClasses", byte[].class); 113 m.setAccessible(true); 114 m.invoke(null, klassbuf); 115 } 116 117 public static class DummyClassLoader extends ClassLoader { 118 119 static ByteBuffer readClassFile(String name) { 120 String testClasses = System.getProperty("test.classes"); 121 File f = new File(testClasses, name); 122 try (FileInputStream fin = new FileInputStream(f)) { 123 FileChannel fc = fin.getChannel(); 124 return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); 125 } catch (IOException e) { 126 throw new RuntimeException("Can't open file: " + f, e); 127 } 128 } 129 130 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 131 Class<?> c; 132 if (TestClass.class.getName().equals(name)) { 133 c = findClass(name); 134 if (resolve) { 135 resolveClass(c); 136 } 137 } else { 138 c = super.loadClass(name, resolve); 139 } 140 return c; 141 } 142 143 protected Class<?> findClass(String name) throws ClassNotFoundException { 144 if (!TestClass.class.getName().equals(name)) { 145 throw new ClassNotFoundException("Unexpected class: " + name); 146 } 147 return defineClass(name, readClassFile(TestClass.class.getName().replace(".", File.separator) + ".class"), null); 148 } 149 150 public DummyClassLoader(String name) { 151 super(name, ClassLoader.getSystemClassLoader()); 152 } 153 } 154 }