1 /* 2 * Copyright (c) 2018, 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.jvm; 27 28 import java.io.ByteArrayOutputStream; 29 import java.io.InputStream; 30 31 import jdk.jfr.Event; 32 import jdk.jfr.FlightRecorder; 33 import jdk.jfr.internal.JVM; 34 35 /* 36 * @test 37 * @key jfr 38 * @summary Unit test for JVM#getUnloadedEventClassCount 39 * 40 * @library /test/lib 41 * @modules jdk.jfr/jdk.jfr.internal 42 * java.base/jdk.internal.misc 43 * 44 * @run main/othervm -Xlog:class+unload -Xlog:gc -Xmx16m jdk.jfr.jvm.TestUnloadEventClassCount 45 */ 46 public class TestUnloadEventClassCount { 47 48 private static final String EVENT_NAME = "jdk.jfr.jvm.TestUnloadEventClassCount$ToBeUnloaded"; 49 50 public static class ToBeUnloaded extends Event { 51 } 52 53 static public class MyClassLoader extends ClassLoader { 54 public MyClassLoader() { 55 super("MyClassLoader", null); 56 } 57 58 public final Class<?> defineClass(String name, byte[] b) { 59 return super.defineClass(name, b, 0, b.length); 60 } 61 } 62 63 public static MyClassLoader myClassLoader; 64 65 public static void main(String[] args) throws Throwable { 66 FlightRecorder.getFlightRecorder(); 67 myClassLoader = createClassLoaderWithEventClass(); 68 System.out.println("MyClassLoader instance created"); 69 long initialCount = JVM.getJVM().getUnloadedEventClassCount(); 70 System.out.println("Initiali unloaded count is " + initialCount); 71 myClassLoader = null; 72 System.out.println("Reference to class loader cleared"); 73 long count = 0; 74 do { 75 System.gc(); 76 System.out.println("GC triggered"); 77 count = JVM.getJVM().getUnloadedEventClassCount(); 78 System.out.println("Unloaded count was " + count); 79 Thread.sleep(1000); // sleep to reduce log 80 } while (count != initialCount + 1); 81 } 82 83 private static MyClassLoader createClassLoaderWithEventClass() throws Exception { 84 String resourceName = EVENT_NAME.replace('.', '/') + ".class"; 85 try (InputStream is = TestUnloadEventClassCount.class.getClassLoader().getResourceAsStream(resourceName)) { 86 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 87 byte[] buffer = new byte[4096]; 88 int byteValue = 0; 89 while ((byteValue = is.read(buffer, 0, buffer.length)) != -1) { 90 baos.write(buffer, 0, byteValue); 91 } 92 baos.flush(); 93 MyClassLoader myClassLoader = new MyClassLoader(); 94 Class<?> eventClass = myClassLoader.defineClass(EVENT_NAME, baos.toByteArray()); 95 if (eventClass == null) { 96 throw new Exception("Could not define test class"); 97 } 98 if (eventClass.getSuperclass() != Event.class) { 99 throw new Exception("Superclass should be jdk.jfr.Event"); 100 } 101 if (eventClass.getSuperclass().getClassLoader() != null) { 102 throw new Exception("Class loader of jdk.jfr.Event should be null"); 103 } 104 if (eventClass.getClassLoader() != myClassLoader) { 105 throw new Exception("Incorrect class loader for event class"); 106 } 107 eventClass.newInstance(); // force <clinit> 108 return myClassLoader; 109 } 110 } 111 }