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 for (ArrayReference arr1: arrays) { 146 for (ArrayReference arr2: arrays) { 147 if (!arraysEquals(arr1, arr2)) { 148 System.out.println("Arrays are different (1):" 149 + "\n - " + arrayToString(arr1) 150 + "\n - " + arrayToString(arr2)); 151 throw new RuntimeException("Arrays are different"); 152 } 153 } 154 } 155 } 156 157 protected void runTests() throws Exception { 158 try { 159 BreakpointEvent bpe = startToMain("ValueArrayReferenceTarg"); 160 ReferenceType cls = bpe.location().declaringType(); 161 162 // Get all arrays. 163 List<ArrayReference> arrays = new ArrayList<>(); 164 List<Field> fields = cls.allFields(); 165 for (Field field: fields) { 166 if (field.name().startsWith("test")) { 167 arrays.add(getArrayFromField(cls, field)); 168 } 169 } 170 171 // Ensure elements in all arrays are equal. 172 verifyArraysEqual(arrays); 173 174 // Update arrays. 175 Value otherValue = getFieldValue(cls, "otherValue"); 176 for (ArrayReference arr: arrays) { 177 fillArrayWithOtherValue(arr, otherValue); 178 System.out.println("Array after update:"); 179 System.out.println(" " + arrayToString(arr)); 180 } 181 182 // Ensure elements in all arrays are equal. 183 verifyArraysEqual(arrays); 184 } finally { 185 // Resume the target until end. 186 listenUntilVMDisconnect(); 187 } 188 } 189 }