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 * @summary Test JVMTI GetClassModifiers with value classes
27 * @enablePreview
28 * @modules java.base/jdk.internal.misc
29 * @run junit/othervm/native --enable-native-access=ALL-UNNAMED ${test.main.class}
30 */
31
32 import java.lang.classfile.ClassFile;
33 import java.util.stream.Stream;
34
35 import org.junit.jupiter.api.Test;
36 import org.junit.jupiter.params.ParameterizedTest;
37 import org.junit.jupiter.params.provider.MethodSource;
38 import static org.junit.jupiter.api.Assertions.*;
39
40 class GetValueClassModifiersTest {
41
42 // member classes to test
43
44 public abstract value class A_V1 { }
45 abstract value class A_V2 { }
46 public value class V1 { }
47 value class V2 { }
48 public value record R_V1() { }
49 value record R_V2() { }
50
51 static Stream<Class<?>> testClasses() {
52 // local classes
53 value class L_V { }
54 abstract value class L_A_V { }
55
56 return Stream.of(
57 Integer.class,
58 Integer[].class,
59
60 A_V1.class,
61 A_V1[].class,
62 A_V2.class,
63 A_V2[].class,
64 V1.class,
65 V1[].class,
66 V2.class,
67 V2.class,
68 R_V1.class,
69 R_V1[].class,
70 R_V2.class,
71 R_V2[].class,
72
73 // local classes
74 L_V.class,
75 L_V[].class,
76 L_A_V.class,
77 L_A_V[].class
78 );
79 }
80
81 static Stream<Class<?>> valueClasses() {
82 return testClasses().filter(Class::isValue);
83 }
84
85 static Stream<Class<?>> arrayClasses() {
86 return testClasses().filter(Class::isArray);
87 }
88
89 @ParameterizedTest
90 @MethodSource("valueClasses")
91 void testValueClass(Class<?> clazz) {
92 assertTrue(clazz.isValue());
93 int mods = jvmtiGetClassModifiers(clazz);
94 assertEquals(0, (mods & ClassFile.ACC_IDENTITY), "ACC_IDENTITY set");
95 assertEquals(clazz.getModifiers(), jvmtiGetClassModifiers(clazz));
96 }
97
98 @ParameterizedTest
99 @MethodSource("arrayClasses")
100 void testArrayClass(Class<?> clazz) {
101 assertTrue(clazz.isArray());
102 int mods = jvmtiGetClassModifiers(clazz);
103 assertEquals(ClassFile.ACC_IDENTITY, (mods & ClassFile.ACC_IDENTITY), "ACC_IDENTITY not set");
104 assertEquals(clazz.getModifiers(), jvmtiGetClassModifiers(clazz));
105 }
106
107 private int jvmtiGetClassModifiers(Class<?> clazz) {
108 return GetClassModifiers.getClassModifiers(clazz);
109 }
110 }