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