1 /*
2 * Copyright (c) 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 /**
25 * @test
26 * @summary Sanity test for ArrayReference (getValue/setValue) with flat arrays
27 *
28 * @modules java.base/jdk.internal.value
29 * @library ..
30 * @enablePreview
31 * @run main/othervm ValueArrayReferenceTest
32 * --add-modules java.base --add-exports java.base/jdk.internal.value=ALL-UNNAMED
33 * -XX:+UseArrayFlattening -XX:+UseFieldFlattening -XX:+UseAtomicValueFlattening -XX:+UseNullableValueFlattening
34 * -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlineLayout -XX:+PrintFlatArrayLayout
35 */
36 import com.sun.jdi.ArrayReference;
37 import com.sun.jdi.Field;
38 import com.sun.jdi.ReferenceType;
39 import com.sun.jdi.Value;
40 import com.sun.jdi.event.BreakpointEvent;
41 import java.util.ArrayList;
42 import java.util.List;
43 import java.util.stream.Collectors;
44 import jdk.internal.value.ValueClass;
45
46 class ValueArrayReferenceTarg {
47 static value class Value {
48 int v;
49 Value() {
50 this(0);
51 }
52 Value(int v) {
53 this.v = v;
54 }
55 public int getValue() {
56 return v;
57 }
58 }
59
60 static int ARRAY_SIZE = 5;
61 static void initArray(Value[] arr) {
62 for (int i = 0; i < arr.length; i++) {
63 arr[i] = new Value(i);
64 }
65 }
66
67 static Value[] testRegularArray;
68 static Value[] testNullableAtomicArray;
69 static Value[] testNonNullNonAtomicArray;
70 static Value[] testNonNullAtomicArray;
71
72 static Value otherValue = new Value(25);
73
74 static {
75 try {
76 testRegularArray = new Value[ARRAY_SIZE];
77 initArray(testRegularArray);
78
79 testNullableAtomicArray = (Value[])ValueClass.newNullableAtomicArray(Value.class, ARRAY_SIZE);
80 initArray(testNullableAtomicArray);
81
82 testNonNullNonAtomicArray = (Value[])ValueClass.newNullRestrictedNonAtomicArray(Value.class, ARRAY_SIZE, Value.class.newInstance());
83 initArray(testNonNullNonAtomicArray);
84
85 testNonNullAtomicArray = (Value[])ValueClass.newNullRestrictedAtomicArray(Value.class, ARRAY_SIZE, Value.class.newInstance());
86 initArray(testNonNullAtomicArray);
87 } catch (Exception ex) {
88 throw new RuntimeException(ex);
89 }
90 }
91
92 public static void main(String[] args) {
93 System.out.println("Hello and goodbye from main");
94 }
95 }
96
97 public class ValueArrayReferenceTest extends TestScaffold {
98
99 ValueArrayReferenceTest (String args[]) {
100 super(args);
101 }
102
103 public static void main(String[] args) throws Exception {
104 new ValueArrayReferenceTest(args).startTests();
105 }
106
107 String arrayToString(ArrayReference array) {
108 List<Value> values = array.getValues();
109 // Mirror.toString reports object type and reference id,
110 // it should be enough to see if objects are different.
111 return values.stream()
112 .map(String::valueOf)
113 .collect(Collectors.joining(", ", "[", "]"));
114 }
115
116 Value getFieldValue(ReferenceType cls, String fieldName) {
117 System.out.println("Getting value from " + fieldName);
118 Value value = cls.getValue(cls.fieldByName(fieldName));
119 System.out.println(" - " + value);
120 return value;
121 }
122
123 ArrayReference getArrayFromField(ReferenceType cls, Field field) throws Exception {
124 System.out.println("Getting array from " + field.name());
125 ArrayReference array = (ArrayReference)cls.getValue(field);
126 System.out.println(" - " + array);
127 System.out.println(" " + arrayToString(array));
128 return array;
129 }
130
131 boolean arraysEquals(ArrayReference arr1, ArrayReference arr2) throws Exception {
132 // Compare string representation of the array (contains object type and id for each element).
133 String s1 = arrayToString(arr1);
134 String s2 = arrayToString(arr2);
135 return s1.equals(s2);
136 }
137
138 void fillArrayWithOtherValue(ArrayReference arr, Value value) throws Exception {
139 for (int i = 0; i < arr.length(); i++) {
140 arr.setValue(i, value);
141 }
142 }
143
144 void verifyArraysEqual(List<ArrayReference> arrays) throws Exception {
145 // Compare 1st and 2nd, 2nd and 3rd, etc.
146 for (int i = 1; i < arrays.size(); i++) { // start from 1
147 ArrayReference arr1 = arrays.get(i - 1);
148 ArrayReference arr2 = arrays.get(i);
149 if (!arraysEquals(arr1, arr2)) {
150 System.out.println("Arrays are different (" + (i - 1) + " and " + i + "):"
151 + "\n - " + arrayToString(arr1)
152 + "\n - " + arrayToString(arr2));
153 throw new RuntimeException("Arrays are different");
154 }
155 }
156 }
157
158 protected void runTests() throws Exception {
159 try {
160 BreakpointEvent bpe = startToMain("ValueArrayReferenceTarg");
161 ReferenceType cls = bpe.location().declaringType();
162
163 // Get all arrays.
164 List<ArrayReference> arrays = new ArrayList<>();
165 List<Field> fields = cls.allFields();
166 for (Field field: fields) {
167 if (field.name().startsWith("test")) {
168 arrays.add(getArrayFromField(cls, field));
169 }
170 }
171
172 // Ensure elements in all arrays are equal.
173 verifyArraysEqual(arrays);
174
175 // Update arrays.
176 Value otherValue = getFieldValue(cls, "otherValue");
177 for (ArrayReference arr: arrays) {
178 fillArrayWithOtherValue(arr, otherValue);
179 System.out.println("Array after update:");
180 System.out.println(" " + arrayToString(arr));
181 }
182
183 // Ensure elements in all arrays are equal.
184 verifyArraysEqual(arrays);
185 } finally {
186 // Resume the target until end.
187 listenUntilVMDisconnect();
188 }
189 }
190 }