1+ /*
2+ * Copyright (c) 2026, 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+ /**
25+ * @test
26+ * @bug 8375125
27+ * @summary Trigger StringTable::clean_dead_entries or SymbolTable::clean_dead_entries
28+ * with -XX:TrimNativeHeapInterval enabled,should not violate lock ordering.
29+ * @requires vm.debug
30+ * @requires vm.gc != "Epsilon"
31+ * @library /test/lib
32+ * @modules java.compiler
33+ * @run main/othervm -Xms128m -Xmx128m
34+ * -XX:TrimNativeHeapInterval=300000
35+ * TestTrimNativeHeapIntervalTablesCleanup string
36+ * @run main/othervm -Xms128m -Xmx128m
37+ * -XX:TrimNativeHeapInterval=300000
38+ * TestTrimNativeHeapIntervalTablesCleanup symbol
39+ */
40+
41+ import java .util .LinkedList ;
42+ import jdk .test .lib .compiler .InMemoryJavaCompiler ;
43+
44+ public class TestTrimNativeHeapIntervalTablesCleanup {
45+
46+ public static void main (String [] args ) throws Exception {
47+ if (args .length != 1 ) {
48+ throw new IllegalArgumentException ("Expected 1 argument: string|symbol" );
49+ }
50+ switch (args [0 ]) {
51+ case "string" :
52+ testStringTableCleanup ();
53+ break ;
54+ case "symbol" :
55+ testSymbolTableCleanup ();
56+ break ;
57+ default :
58+ throw new IllegalArgumentException ("Unknown mode: " + args [0 ]);
59+ }
60+ System .out .println ("passed: " + args [0 ]);
61+ }
62+
63+ static void testStringTableCleanup () throws Exception {
64+ final int rounds = 30 ;
65+ final int maxSize = 200_000 ;
66+ final int pruneEvery = 50_000 ;
67+ final int pruneCount = 25_000 ;
68+ long stringNum = 0 ;
69+
70+ for (int round = 0 ; round < rounds ; round ++) {
71+ LinkedList <String > list = new LinkedList <>();
72+ for (int i = 0 ; i < maxSize ; i ++, stringNum ++) {
73+ if (i != 0 && (i % pruneEvery ) == 0 ) {
74+ int toRemove = Math .min (pruneCount , list .size ());
75+ list .subList (0 , toRemove ).clear ();
76+ }
77+ list .push (Long .toString (stringNum ).intern ());
78+ }
79+ System .gc ();
80+ Thread .sleep (1000 );
81+ }
82+ }
83+
84+ static void testSymbolTableCleanup () throws Exception {
85+ final int rounds = 10 ;
86+ final int classesPerRound = 100 ;
87+
88+ for (int r = 0 ; r < rounds ; r ++) {
89+ for (int i = 0 ; i < classesPerRound ; i ++) {
90+ String cn = "C" + r + "_" + i ;
91+ byte [] bytes = InMemoryJavaCompiler .compile (
92+ cn ,
93+ "public class " + cn + " { int m" + i + "() { return " + i + "; } }"
94+ );
95+ new ClassLoader (null ) {
96+ @ Override
97+ protected Class <?> findClass (String name ) throws ClassNotFoundException {
98+ if (!name .equals (cn )) throw new ClassNotFoundException (name );
99+ return defineClass (name , bytes , 0 , bytes .length );
100+ }
101+ }.loadClass (cn ).getDeclaredConstructor ().newInstance ();
102+ }
103+ System .gc ();
104+ Thread .sleep (1000 );
105+ }
106+ }
107+ }
0 commit comments