1 /*
 2  * Copyright (c) 2018, 2025, 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.
 8  *
 9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package jdk.jfr.event.oldobject;
25 
26 import java.lang.reflect.Array;
27 import java.util.ArrayList;
28 import java.util.List;
29 
30 import jdk.jfr.Recording;
31 import jdk.jfr.consumer.RecordedClass;
32 import jdk.jfr.consumer.RecordedEvent;
33 import jdk.jfr.consumer.RecordedObject;
34 import jdk.jfr.internal.test.WhiteBox;
35 import jdk.test.lib.Asserts;
36 import jdk.test.lib.jfr.EventNames;
37 import jdk.test.lib.jfr.Events;
38 
39 /**
40  * @test
41  * @requires vm.flagless
42  * @requires vm.hasJFR
43  * @requires vm.flagless
44  * @comment Marked as flagless until JDK-8322597 is fixed
45  * @library /test/lib /test/jdk
46  * @modules jdk.jfr/jdk.jfr.internal.test
47  * @run main/othervm -XX:TLABSize=2k -Xmx64m jdk.jfr.event.oldobject.TestClassLoaderLeak
48  */
49 public class TestClassLoaderLeak {
50 
51     public static List<Object> classObjects = new ArrayList<>(OldObjects.MIN_SIZE);
52 
53     public static void main(String[] args) throws Exception {
54         WhiteBox.setWriteAllObjectSamples(true);
55 
56         try (Recording r = new Recording()) {
57             r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity");
58             r.start();
59             TestClassLoader testClassLoader = new TestClassLoader();
60             for (Class<?> clazz : testClassLoader.loadClasses(OldObjects.MIN_SIZE / 200)) {
61                 // Allocate array to trigger sampling code path for interpreter / c1
62                 for (int i = 0; i < 200; i++) {
63                     Object classArray = Array.newInstance(clazz, 20);
64                     // No need to fill whole array
65                     for (int j = 0; j < 5; j++) {
66                         Array.set(classArray, j, clazz.getConstructors()[0].newInstance());
67                     }
68                     classObjects.add(classArray);
69                 }
70             }
71             r.stop();
72             List<RecordedEvent> events = Events.fromRecording(r);
73             Events.hasEvents(events);
74             for (RecordedEvent e : events) {
75                 System.out.println(e);
76                 RecordedObject object = e.getValue("object");
77                 RecordedClass rc = object.getValue("type");
78                 if (rc.getName().contains("TestClass")) {
79                     return;
80                 }
81             }
82             Asserts.fail("Could not find class leak");
83         }
84     }
85 }