1 /*
  2  * Copyright (c) 2018, 2024, 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 package runtime.valhalla.inlinetypes;
 25 
 26 import jdk.internal.value.ValueClass;
 27 import jdk.internal.vm.annotation.ImplicitlyConstructible;
 28 import jdk.internal.vm.annotation.LooselyConsistentValue;
 29 import jdk.internal.vm.annotation.NullRestricted;
 30 
 31 import java.lang.reflect.Array;
 32 import java.util.Arrays;
 33 import java.util.ArrayList;
 34 import java.util.List;
 35 
 36 import static jdk.test.lib.Asserts.*;
 37 
 38 /*
 39  * @test InlineTypeArray
 40  * @summary Plain array test for Inline Types
 41  * @modules java.base/jdk.internal.value
 42  *          java.base/jdk.internal.vm.annotation
 43  * @library /test/lib
 44  * @enablePreview
 45  * @compile --source 24 InlineTypeArray.java Point.java Long8Inline.java Person.java
 46  * @run main/othervm -XX:FlatArrayElementMaxSize=-1 runtime.valhalla.inlinetypes.InlineTypeArray
 47  * @run main/othervm -XX:FlatArrayElementMaxSize=0 runtime.valhalla.inlinetypes.InlineTypeArray
 48  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable=* runtime.valhalla.inlinetypes.InlineTypeArray
 49  */
 50 public class InlineTypeArray {
 51     public static void main(String[] args) {
 52         InlineTypeArray inlineTypeArray = new InlineTypeArray();
 53         inlineTypeArray.run();
 54     }
 55 
 56     public void run() {
 57         testClassForName();
 58         testSimplePointArray();
 59         testLong8Array();
 60         testMixedPersonArray();
 61         testMultiDimPointArray();
 62         testComposition();
 63 
 64         testSanityCheckcasts();
 65         testObjectArrayOfInlines();
 66 
 67         testReflectArray();
 68         testUtilArrays();
 69 
 70         testInlineArrayOom();
 71     }
 72 
 73     void testClassForName() {
 74         String arrayClsName = "[Lruntime.valhalla.inlinetypes.Point;";
 75         try {
 76             Class<?> arrayCls = Class.forName(arrayClsName);
 77             assertTrue(arrayCls.isArray(), "Expected an array class");
 78 
 79             arrayClsName = "[" + arrayClsName;
 80             Class<?> mulArrayCls = Class.forName(arrayClsName);
 81             assertTrue(mulArrayCls.isArray());
 82             assertTrue(mulArrayCls.getComponentType() == arrayCls);
 83         }
 84         catch (ClassNotFoundException cnfe) {
 85             fail("Class.forName(" + arrayClsName + ") failed", cnfe);
 86         }
 87     }
 88 
 89     void testSimplePointArray() {
 90         Point[] defaultPoint = (Point[])ValueClass.newNullRestrictedArray(Point.class, 1);
 91         Point p = defaultPoint[0];
 92         assertEquals(p.x, 0, "invalid default loaded from array");
 93         assertEquals(p.y, 0, "invalid default loaded from array");
 94         boolean gotNpe = false;
 95         try {
 96             defaultPoint[0] = (Point) getNull();
 97         } catch (NullPointerException npe) {
 98             gotNpe = true;
 99         }
100         assertTrue(gotNpe, "Expected NullPointerException");
101 
102         Point[] points = createSimplePointArray();
103         System.gc(); // check that VTs survive GC
104         checkSimplePointArray(points);
105         assertTrue(points instanceof Point[], "Instance of");
106 
107         testSimplePointArrayCopy();
108 
109         // Locked/unlocked flat array type checks
110         points = createSimplePointArray();
111         Point[] pointsCopy = (Point[])ValueClass.newNullRestrictedArray(Point.class, points.length);
112         synchronized (points) {
113             assertTrue(points instanceof Point[], "Instance of");
114             checkSimplePointArray(points);
115             System.arraycopy(points, 0, pointsCopy, 0, points.length);
116             synchronized (pointsCopy) {
117                 assertTrue(pointsCopy instanceof Point[], "Instance of");
118                 checkSimplePointArray(pointsCopy);
119                 System.gc();
120             }
121             System.gc();
122         }
123         assertTrue(pointsCopy instanceof Point[], "Instance of");
124         checkSimplePointArray(pointsCopy);
125     }
126 
127     void testSimplePointArrayCopy() {
128         Point[] points = createSimplePointArray();
129         Point[] pointsCopy = (Point[])ValueClass.newNullRestrictedArray(Point.class, points.length);
130         System.arraycopy(points, 0, pointsCopy, 0, points.length);
131         checkSimplePointArray(pointsCopy);
132 
133         // Conjoint, overlap...left
134         System.arraycopy(points, 0, points, 1, 2);
135         checkArrayElementsEqual(points, new Point[] { pointsCopy[0], pointsCopy[0], pointsCopy[1], pointsCopy[3] });
136 
137         // Conjoint, overlap...right
138         points = createSimplePointArray();
139         System.arraycopy(points, 2, points, 1, 2);
140         checkArrayElementsEqual(points, new Point[] { pointsCopy[0], pointsCopy[2], pointsCopy[3], pointsCopy[3] });
141     }
142 
143     static Point[] createSimplePointArray() {
144         Point[] ps = (Point[])ValueClass.newNullRestrictedArray(Point.class, 4);
145         assertEquals(ps.length, 4, "Length");
146         ps.toString();
147         ps[0] = new Point(1, 2);
148         ps[1] = new Point(3, 4);
149         ps[2] = new Point(5, 6);
150         ps[3] = new Point(7, 8);
151         boolean sawOob = false;
152         try {
153             ps[ps.length] = new Point(0, 0);
154         } catch (ArrayIndexOutOfBoundsException aioobe) { sawOob = true; }
155         assertTrue(sawOob, "Didn't see AIOOBE");
156         return ps;
157     }
158 
159     static void checkSimplePointArray(Point[] points) {
160         assertEquals(points[0].x, 1, "invalid 0 point x value");
161         assertEquals(points[0].y, 2, "invalid 0 point y value");
162         assertEquals(points[1].x, 3, "invalid 1 point x value");
163         assertEquals(points[1].y, 4, "invalid 1 point y value");
164         assertEquals(points[2].x, 5, "invalid 2 point x value");
165         assertEquals(points[2].y, 6, "invalid 2 point y value");
166         assertEquals(points[3].x, 7, "invalid 3 point x value");
167         assertEquals(points[3].y, 8, "invalid 3 point y value");
168     }
169 
170     void testLong8Array() {
171         Long8Inline[] values = (Long8Inline[])ValueClass.newNullRestrictedArray(Long8Inline.class, 3);
172         assertEquals(values.length, 3, "length");
173         values.toString();
174         Long8Inline value = values[1];
175         long zl = 0;
176         Long8Inline.check(value, zl, zl, zl, zl, zl, zl, zl, zl);
177         values[1] = new Long8Inline(1, 2, 3, 4, 5, 6, 7, 8);
178         value = values[1];
179         Long8Inline.check(value, 1, 2, 3, 4, 5, 6, 7, 8);
180 
181         Long8Inline[] copy = (Long8Inline[])ValueClass.newNullRestrictedArray(Long8Inline.class, values.length);
182         System.arraycopy(values, 0, copy, 0, values.length);
183         value = copy[1];
184         Long8Inline.check(value, 1, 2, 3, 4, 5, 6, 7, 8);
185     }
186 
187     void testMixedPersonArray() {
188         Person[] people = (Person[])ValueClass.newNullRestrictedArray(Person.class, 3);
189 
190         people[0] = new Person(1, "First", "Last");
191         assertEquals(people[0].getId(), 1, "Invalid Id person");
192         assertEquals(people[0].getFirstName(), "First", "Invalid First Name");
193         assertEquals(people[0].getLastName(), "Last", "Invalid Last Name");
194 
195         people[1] = new Person(2, "Jane", "Wayne");
196         people[2] = new Person(3, "Bob", "Dobalina");
197 
198         Person[] peopleCopy = (Person[])ValueClass.newNullRestrictedArray(Person.class, people.length);
199         System.arraycopy(people, 0, peopleCopy, 0, people.length);
200         assertEquals(peopleCopy[2].getId(), 3, "Invalid Id");
201         assertEquals(peopleCopy[2].getFirstName(), "Bob", "Invalid First Name");
202         assertEquals(peopleCopy[2].getLastName(), "Dobalina", "Invalid Last Name");
203     }
204 
205     void testMultiDimPointArray() {
206         /*
207         Point[][][] multiPoints = new Point[2][3][4];
208         assertEquals(multiPoints.length, 2, "1st dim length");
209         assertEquals(multiPoints[0].length, 3, "2st dim length");
210         assertEquals(multiPoints[0][0].length, 4, "3rd dim length");
211 
212         Point defaultPoint = multiPoints[1][2][3];
213         assertEquals(defaultPoint.x, 0, "invalid point x value");
214         assertEquals(defaultPoint.y, 0, "invalid point x value");
215         */
216     }
217 
218     void testReflectArray() {
219         // Check the java.lang.reflect.Array.newInstance methods...
220         Class<?> cls = (Class<?>) Point[].class;
221         Point[][] array = (Point[][]) Array.newInstance(cls, 1);
222         assertEquals(array.length, 1, "Incorrect length");
223         assertTrue(array[0] == null, "Expected NULL");
224 
225         Point[][][] array3 = (Point[][][]) Array.newInstance(cls, 1, 2);
226         assertEquals(array3.length, 1, "Incorrect length");
227         assertEquals(array3[0].length, 2, "Incorrect length");
228         assertTrue(array3[0][0] == null, "Expected NULL");
229 
230         // Now create ObjArrays of InlineArray...
231         Point[][] barray = (Point[][]) Array.newInstance(Point.class, 1, 2);
232         assertEquals(barray.length, 1, "Incorrect length");
233         assertEquals(barray[0].length, 2, "Incorrect length");
234         barray[0][1] = new Point(1, 2);
235         Point pb = barray[0][1];
236         int x = pb.getX();
237         assertEquals(x, 1, "Bad Point Value");
238     }
239 
240     @ImplicitlyConstructible
241     @LooselyConsistentValue
242     static value class MyInt implements Comparable<MyInt> {
243         int value;
244 
245         private MyInt() { this(0); }
246         private MyInt(int v) { value = v; }
247         public int getValue() { return value; }
248         public String toString() { return "MyInt: " + getValue(); }
249         public int compareTo(MyInt that) { return Integer.compare(this.getValue(), that.getValue()); }
250         public boolean equals(Object o) {
251             if (o instanceof MyInt) {
252                 return this.getValue() == ((MyInt) o).getValue();
253             }
254             return false;
255         }
256 
257         public static MyInt create(int v) {
258             return new MyInt(v);
259         }
260 
261         // Null-able fields here are a temp hack to avoid ClassCircularityError
262         public static final MyInt MIN = MyInt.create(Integer.MIN_VALUE);
263         public static final MyInt ZERO = MyInt.create(0);
264         public static final MyInt MAX = MyInt.create(Integer.MAX_VALUE);
265     }
266 
267     static MyInt staticMyInt;
268     static MyInt[] staticMyIntArray;
269     static MyInt[][] staticMyIntArrayArray;
270 
271     static {
272         staticMyInt = MyInt.create(-1);
273         staticMyIntArray = (MyInt[])ValueClass.newNullRestrictedArray(MyInt.class, 1);
274         staticMyIntArray[0] = staticMyInt;
275         staticMyIntArrayArray = new MyInt[][] { staticMyIntArray, staticMyIntArray };
276     }
277 
278     static interface SomeSecondaryType {
279         default String hi() { return "Hi"; }
280     }
281 
282     @ImplicitlyConstructible
283     @LooselyConsistentValue
284     static value class MyOtherInt implements SomeSecondaryType {
285         final int value;
286         private MyOtherInt() { value = 0; }
287     }
288 
289     void testSanityCheckcasts() {
290         MyInt[] myInts = (MyInt[])ValueClass.newNullRestrictedArray(MyInt.class, 1);
291         assertTrue(myInts instanceof Object[]);
292         assertTrue(myInts instanceof Comparable[]);
293         assertTrue(myInts instanceof MyInt[]);
294 
295         Class<?> cls = MyInt.class;
296         assertTrue(cls.isValue());
297         Object arrObj = Array.newInstance(cls, 1);
298         assertTrue(arrObj instanceof Object[], "Not Object array");
299         assertTrue(arrObj instanceof Comparable[], "Not Comparable array");
300         assertTrue(arrObj instanceof MyInt[], "Not MyInt array");
301 
302         Object[] arr = (Object[]) arrObj;
303         assertTrue(arr instanceof Comparable[], "Not Comparable array");
304         assertTrue(arr instanceof MyInt[], "Not MyInt array");
305         Comparable[] comparables = (Comparable[])arr;
306         MyInt[] myIntArr = (MyInt[]) arr;
307 
308         // multi-dim, check secondary array types are setup...
309         MyOtherInt[][] matrix = new MyOtherInt[1][1];
310         assertTrue(matrix[0] instanceof MyOtherInt[]);
311         assertTrue(matrix[0] instanceof SomeSecondaryType[]);
312         assertTrue(matrix[0] instanceof MyOtherInt[]);
313 
314         // Box types vs Inline...
315         MyInt[] myValueRefs = new MyInt[1];
316         assertTrue(myValueRefs instanceof MyInt[]);
317         assertTrue(myValueRefs instanceof Object[]);
318         assertTrue(myValueRefs instanceof Comparable[]);
319 
320         MyInt[][] myMdValueRefs = new MyInt[1][1];
321         assertTrue(myMdValueRefs[0] instanceof MyInt[]);
322         assertTrue(myMdValueRefs[0] instanceof Object[]);
323         assertTrue(myMdValueRefs[0] instanceof Comparable[]);
324 
325         // Did we break checkcast...
326         MyInt[]     va1 = (MyInt[])null;
327         MyInt[]     va2 = null;
328         MyInt[][]   va3 = (MyInt[][])null;
329         MyInt[][][] va4 = (MyInt[][][])null;
330     }
331 
332 
333     void testUtilArrays() {
334         // Sanity check j.u.Arrays
335 
336         // cast to q-type temp effect of avoiding circularity error (decl static MyInt.ref)
337         MyInt[] myInts = (MyInt[])ValueClass.newNullRestrictedArray(MyInt.class, 2);
338         myInts[0] = (MyInt) MyInt.MAX;
339         myInts[1] = (MyInt) MyInt.MIN;
340 
341         // Sanity sort another copy
342         MyInt[] copyMyInts = (MyInt[]) Arrays.copyOf(myInts, myInts.length + 1);
343         MyInt[] expected = (MyInt[])ValueClass.newNullRestrictedArray(MyInt.class, 3);
344         expected[0] = myInts[0];
345         expected[1] = myInts[1];
346         expected[2] = (MyInt) MyInt.ZERO;
347         checkArrayElementsEqual(copyMyInts, expected);
348 
349         Arrays.sort(copyMyInts);
350         expected = (MyInt[])ValueClass.newNullRestrictedArray(MyInt.class, 3);
351         expected[0] = (MyInt) MyInt.MIN;
352         expected[1] = (MyInt) MyInt.ZERO;
353         expected[2] = (MyInt) MyInt.MAX;
354         checkArrayElementsEqual(copyMyInts, expected);
355 
356         List myIntList = Arrays.asList(copyMyInts);
357 
358         MyInt[] dest = (MyInt[])ValueClass.newNullRestrictedArray(MyInt.class, copyMyInts.length);
359         checkArrayElementsEqual(copyMyInts, myIntList.toArray(dest));
360         // This next line needs testMixedLayoutArrays to work
361         checkArrayElementsEqual(copyMyInts, myIntList.toArray());
362 
363         // Sanity check j.u.ArrayList
364         ArrayList<MyInt> aList = new ArrayList<MyInt>(Arrays.asList(copyMyInts));
365         assertTrue(aList.indexOf(MyInt.MIN) == 0, "Bad Index");
366         assertTrue(aList.indexOf(MyInt.ZERO) == 1, "Bad Index");
367         assertTrue(aList.indexOf(MyInt.MAX) == 2, "Bad Index");
368 
369         aList.remove(2);
370         aList.add(MyInt.create(5));
371     }
372 
373 
374     void testObjectArrayOfInlines() {
375         testSanityObjectArrays();
376         testMixedLayoutArrays();
377     }
378 
379     void testSanityObjectArrays() {
380         Object[] objects = new Object[2];
381         assertTrue(objects[0] == null && objects[1] == null, "Not null ?");
382 
383         objects[0] = MyInt.create(1);
384         objects[1] = Integer.valueOf(2);
385         assertTrue(objects[0].equals(MyInt.create(1)), "Bad Value");
386         assertTrue(objects[1].equals(Integer.valueOf(2)), "Bad Object");
387 
388         Comparable[] copyComparables = new Comparable[objects.length];
389         System.arraycopy(objects, 0, copyComparables, 0, objects.length);
390         checkArrayElementsEqual(objects, copyComparables);
391 
392         objects[0] = null;
393         objects[1] = null;
394         assertTrue(objects[0] == null && objects[1] == null, "Not null ?");
395 
396         Comparable[] comparables = new Comparable[2];
397         assertTrue(comparables[0] == null && comparables[1] == null, "Not null ?");
398         comparables[0] = MyInt.create(3);
399         comparables[1] = Integer.valueOf(4);
400         assertTrue(comparables[0].equals(MyInt.create(3)), "Bad Value");
401         assertTrue(comparables[1].equals(Integer.valueOf(4)), "Bad Object");
402 
403         Object[] copyObjects = new Object[2];
404         System.arraycopy(comparables, 0, copyObjects, 0, comparables.length);
405         checkArrayElementsEqual(comparables, copyObjects);
406 
407         comparables[0] = null;
408         comparables[1] = null;
409         assertTrue(comparables[0] == null && comparables[1] == null, "Not null ?");
410 
411         MyInt[] myIntRefArray = new MyInt[1];
412         assertTrue(myIntRefArray[0] == null, "Got: " + myIntRefArray[0]);
413         myIntRefArray[0] = null;
414 
415         MyInt[] srcNulls = new MyInt[2];
416         MyInt[] dstNulls = new MyInt[2];
417         System.arraycopy(srcNulls, 0, dstNulls, 0, 2);
418         checkArrayElementsEqual(srcNulls, dstNulls);
419         srcNulls[1] = MyInt.create(1);
420         System.arraycopy(srcNulls, 0, dstNulls, 0, 2);
421         checkArrayElementsEqual(srcNulls, dstNulls);
422 
423 
424         // Locked/unlocked flat array type checks
425         synchronized (srcNulls) {
426             System.arraycopy(srcNulls, 0, dstNulls, 0, 2);
427             checkArrayElementsEqual(srcNulls, dstNulls);
428             System.gc();
429         }
430         System.gc();
431         checkArrayElementsEqual(srcNulls, dstNulls);
432     }
433 
434     void testMixedLayoutArrays() {
435         Object[] objArray = new Object[3];
436         Comparable[] compArray = new Comparable[3];
437         MyInt[] valArray = new MyInt[] { (MyInt) MyInt.MIN, (MyInt) MyInt.ZERO, (MyInt) MyInt.MAX };
438 
439         arrayCopy(valArray, 0, objArray, 0, 3);
440         checkArrayElementsEqual(valArray, objArray);
441         arrayCopy(valArray, 0, objArray, 0, 3);
442 
443         objArray = new Object[3];
444         System.arraycopy(valArray, 0, objArray, 0, 3);
445         checkArrayElementsEqual(valArray, objArray);
446 
447         System.arraycopy(valArray, 0, compArray, 0, 3);
448         checkArrayElementsEqual(valArray, compArray);
449 
450         valArray = (MyInt[])ValueClass.newNullRestrictedArray(MyInt.class, 3);
451         valArray[0] = (MyInt) MyInt.ZERO;
452         valArray[1] = (MyInt) MyInt.ZERO;
453         valArray[2] = (MyInt) MyInt.ZERO;
454         System.arraycopy(compArray, 0, valArray, 0, 3);
455         checkArrayElementsEqual(valArray, compArray);
456 
457         valArray = (MyInt[])ValueClass.newNullRestrictedArray(MyInt.class, 3);
458         valArray[0] = (MyInt) MyInt.ZERO;
459         valArray[1] = (MyInt) MyInt.ZERO;
460         valArray[2] = (MyInt) MyInt.ZERO;
461         System.arraycopy(objArray, 0, valArray, 0, 3);
462         checkArrayElementsEqual(valArray, objArray);
463 
464         // Sanity check dst == src
465         System.arraycopy(valArray, 0, valArray, 0, 3);
466         checkArrayElementsEqual(valArray, objArray);
467 
468         objArray[0] = "Not an inline object";
469         try {
470             System.arraycopy(objArray, 0, valArray, 0, 3);
471             throw new RuntimeException("Expected ArrayStoreException");
472         } catch (ArrayStoreException ase) {}
473 
474         MyInt[] myIntRefArray = new MyInt[3];
475         System.arraycopy(valArray, 0, myIntRefArray, 0, 3);
476         checkArrayElementsEqual(valArray, myIntRefArray);
477 
478         myIntRefArray[0] = null;
479         try {
480             System.arraycopy(myIntRefArray, 0, valArray, 0, 3);
481             throw new RuntimeException("Expected NullPointerException");
482         } catch (NullPointerException npe) {}
483     }
484 
485     @ImplicitlyConstructible
486     @LooselyConsistentValue
487     static value class MyPoint {
488         @NullRestricted
489         MyInt x;
490         @NullRestricted
491         MyInt y;
492 
493         private MyPoint() { this(0, 0); }
494         private MyPoint(int x, int y) {
495             this.x = new MyInt(x);
496             this.y = new MyInt(y);
497         }
498         public boolean equals(Object that) {
499             if (that instanceof MyPoint) {
500                 MyPoint thatPoint = (MyPoint) that;
501                 return x.equals(thatPoint.x) && java.util.Objects.equals(y, thatPoint.y);
502             }
503             return false;
504         }
505         static MyPoint create(int x) {
506             return new MyPoint(x, x);
507         }
508         static MyPoint create(int x, int y) {
509             return new MyPoint(x, y);
510         }
511         @NullRestricted
512         static final MyPoint ORIGIN = create(0);
513     }
514 
515     void testComposition() {
516         // Test array operations with compostion of inline types, check element payload is correct...
517         MyPoint a = MyPoint.create(1, 2);
518         MyPoint b = MyPoint.create(7, 21);
519         MyPoint c = MyPoint.create(Integer.MAX_VALUE, Integer.MIN_VALUE);
520 
521         MyPoint[] pts = (MyPoint[])ValueClass.newNullRestrictedArray(MyPoint.class, 3);
522         if (!pts[0].equals(MyPoint.ORIGIN)) {
523             throw new RuntimeException("Equals failed: " + pts[0] + " vs " + MyPoint.ORIGIN);
524         }
525         pts = (MyPoint[])ValueClass.newNullRestrictedArray(MyPoint.class, 3);
526         pts[0] = a;
527         pts[1] = b;
528         pts[2] = c;
529         checkArrayElementsEqual(pts, new Object[] { a, b, c});
530         Object[] oarr = new Object[3];
531 
532         arrayCopy(pts, 0, oarr, 0, 3);
533         checkArrayElementsEqual(pts, oarr);
534 
535         oarr = new Object[3];
536         System.arraycopy(pts, 0, oarr, 0, 3);
537         checkArrayElementsEqual(pts, oarr);
538 
539         System.arraycopy(oarr, 0, pts, 0, 3);
540         checkArrayElementsEqual(pts, oarr);
541 
542         oarr = new Object[3];
543         try {
544             System.arraycopy(oarr, 0, pts, 0, 3);
545             throw new RuntimeException("Expected NPE");
546         }
547         catch (NullPointerException npe) {}
548 
549         oarr = new Object[3];
550         oarr[0] = new Object();
551         try {
552             System.arraycopy(oarr, 0, pts, 0, 3);
553             throw new RuntimeException("Expected ASE");
554         }
555         catch (ArrayStoreException ase) {}
556     }
557 
558     void checkArrayElementsEqual(MyInt[] arr1, Object[] arr2) {
559         assertTrue(arr1.length == arr2.length, "Bad length");
560         for (int i = 0; i < arr1.length; i++) {
561             assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal");
562         }
563     }
564 
565     void checkArrayElementsEqual(MyPoint[] arr1, Object[] arr2) {
566         assertTrue(arr1.length == arr2.length, "Bad length");
567         for (int i = 0; i < arr1.length; i++) {
568             assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal");
569         }
570     }
571 
572     void checkArrayElementsEqual(Object[] arr1, Object[] arr2) {
573         assertTrue(arr1.length == arr2.length, "Bad length");
574         for (int i = 0; i < arr1.length; i++) {
575             assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal");
576         }
577     }
578 
579     void arrayCopy(MyInt[] src, int srcPos, Object[] dst, int dstPos, int length) {
580         for (int i = 0; i < length ; i++) {
581             dst[dstPos++] = src[srcPos++];
582         }
583     }
584     void arrayCopy(MyPoint[] src, int srcPos, Object[] dst, int dstPos, int length) {
585         for (int i = 0; i < length ; i++) {
586             dst[dstPos++] = src[srcPos++];
587         }
588     }
589 
590     Object getNull() { return null; }
591 
592 
593     void testInlineArrayOom() {
594         int size = Integer.MAX_VALUE;
595         try {
596             MyPoint[] pts = new MyPoint[size];
597             throw new RuntimeException("Excepted OOM");
598         } catch (OutOfMemoryError oom) {}
599     }
600 
601 }