1 /*
2 * Copyright (c) 2025, 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 that isValue and modifiers return correct results for value classes & arrays
27 * @library /test/lib
28 * @enablePreview false
29 * @modules java.base/jdk.internal.misc
30 * java.base/jdk.internal.value
31 * @run junit/othervm IdentityReflectionTest
32 * @run junit/othervm --enable-preview IdentityReflectionTest
33 */
34
35 import org.junit.jupiter.api.Test;
36
37 import java.lang.classfile.ClassFile;
38 import java.lang.reflect.AccessFlag;
39 import java.lang.reflect.Modifier;
40 import java.util.Set;
41
42 import jdk.internal.misc.PreviewFeatures;
43
44 import static jdk.test.lib.Asserts.*;
45
46 public class IdentityReflectionTest {
47
48 static final boolean PREVIEW = PreviewFeatures.isEnabled();
49
50 static final Class<?>[] valueClasses = {
51 Number.class,
52 Record.class,
53
54 Byte.class,
55 Short.class,
56 Integer.class,
57 Long.class,
58 Float.class,
59 Double.class,
60 Boolean.class,
61 Character.class,
62
63 java.util.Optional.class,
64 java.util.OptionalDouble.class,
65 java.util.OptionalInt.class,
66 java.util.OptionalLong.class,
67
68 java.time.Duration.class,
69 java.time.Instant.class,
70 java.time.LocalDate.class,
71 java.time.LocalDateTime.class,
72 java.time.LocalTime.class,
73 java.time.MonthDay.class,
74 java.time.OffsetDateTime.class,
75 java.time.OffsetTime.class,
76 java.time.Period.class,
77 java.time.Year.class,
78 java.time.YearMonth.class,
79 java.time.ZonedDateTime.class,
80
81 java.time.chrono.HijrahDate.class,
82 java.time.chrono.JapaneseDate.class,
83 java.time.chrono.MinguoDate.class,
84 java.time.chrono.ThaiBuddhistDate.class,
85 };
86
87 static final Class<?>[] identityClasses = {
88 Object.class,
89 String.class,
90 Thread.class,
91 java.math.BigInteger.class,
92 java.math.BigDecimal.class,
93 Integer[].class,
94 Thread[].class,
95 };
96
97 @Test
98 void testIsValue() {
99 checkIsValue(int.class, false);
100 checkIsValue(Runnable.class, false);
101 for (Class<?> c : valueClasses) {
102 checkIsValue(c, PREVIEW);
103 }
104 for (Class<?> c : identityClasses) {
105 checkIsValue(c, false);
106 }
107 }
108
109 @SuppressWarnings("preview")
110 void checkIsValue(Class<?> c, boolean expected) {
111 assertEquals(expected, c.isValue(),
112 c + " " + (expected ? "is" : "is not") + " a value class");
113 }
114
115 @Test
116 void testModifiers() {
117 checkIdentityModifier(int.class, false);
118 checkIdentityModifier(Runnable.class, false);
119 for (Class<?> c : valueClasses) {
120 checkIdentityModifier(c, false);
121 }
122 for (Class<?> c : identityClasses) {
123 checkIdentityModifier(c, PREVIEW);
124 }
125 }
126
127 @SuppressWarnings("preview")
128 void checkIdentityModifier(Class<?> c, boolean expected) {
129 int mod = c.getModifiers();
130 assertEquals(expected, (mod & ClassFile.ACC_IDENTITY) != 0,
131 "Modifier of " + c + " (" + Integer.toHexString(mod) + ") " +
132 (expected ? "should" : "should not") + " have ACC_IDENTITY set");
133 }
134
135 @Test
136 void testAccessFlags() {
137 checkIdentityAccessFlag(int.class, false);
138 checkIdentityAccessFlag(Runnable.class, false);
139 for (Class<?> c : valueClasses) {
140 checkIdentityAccessFlag(c, false);
141 }
142 for (Class<?> c : identityClasses) {
143 checkIdentityAccessFlag(c, PREVIEW);
144 }
145 }
146
147 @SuppressWarnings("preview")
148 void checkIdentityAccessFlag(Class<?> c, boolean expected) {
149 Set<AccessFlag> acc = c.accessFlags();
150 assertEquals(expected, acc.contains(AccessFlag.IDENTITY),
151 "Access flags of " + c + " (" + acc + ") " +
152 (expected ? "should" : "should not") + " contain IDENTITY");
153 }
154 }