1 /*
  2  * Copyright (c) 2016, 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  * @bug 8155643 8268125 8270461 8270098 8332959
 27  * @summary Test Object.clone() intrinsic.
 28  * @modules java.base/java.lang:+open
 29  *
 30  * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-ReduceInitialCardMarks
 31  *                   -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
 32  *                   -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
 33  *                   compiler.arraycopy.TestObjectArrayClone
 34  * @run main/othervm -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
 35  *                   -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
 36  *                   compiler.arraycopy.TestObjectArrayClone
 37  * @run main/othervm -Xbatch -XX:-UseTypeProfile
 38  *                   -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
 39  *                   -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
 40  *                   -XX:CompileCommand=compileonly,*::invokeVirtual
 41  *                   compiler.arraycopy.TestObjectArrayClone
 42  */
 43 
 44 package compiler.arraycopy;
 45 
 46 import java.lang.invoke.*;
 47 import java.lang.reflect.InvocationTargetException;
 48 import java.lang.reflect.Method;
 49 
 50 class Payload implements Cloneable {
 51     boolean b;
 52     int i;
 53     char c;
 54     String str;
 55     short s;
 56     int i2;
 57 
 58     public Payload(boolean b, int i, char c, String str, short s, int i2) {
 59         super();
 60         this.b = b;
 61         this.i = i;
 62         this.c = c;
 63         this.str = str;
 64         this.s = s;
 65         this.i2 = i2;
 66     }
 67 
 68     public Payload clonep() {
 69         try {
 70             return (Payload) super.clone();
 71         } catch (CloneNotSupportedException e) {
 72             return null;
 73         }
 74     }
 75 }
 76 
 77 class Payload2 implements Cloneable {
 78     boolean b;
 79     int i;
 80     char c;
 81     String str;
 82     short s;
 83     int i2;
 84     boolean b2;
 85     int i3;
 86     char c2;
 87     String str2;
 88     short s2;
 89     int i4;
 90 
 91     public Payload2(boolean b, int i, char c, String str, short s, int i2, boolean b2, int i3, char c2, String str2,
 92             short s2, int i4) {
 93         super();
 94         this.b = b;
 95         this.i = i;
 96         this.c = c;
 97         this.str = str;
 98         this.s = s;
 99         this.i2 = i2;
100         this.b2 = b2;
101         this.i3 = i3;
102         this.c2 = c2;
103         this.str2 = str2;
104         this.s2 = s2;
105         this.i4 = i4;
106     }
107 
108     public Payload2 clonep() {
109         try {
110             return (Payload2) super.clone();
111         } catch(CloneNotSupportedException e) {
112             return null;
113         }
114     }
115 }
116 
117 public class TestObjectArrayClone {
118 
119     public static String[] escape_arr;
120 
121     public static String str1 = new String("1");
122     public static String str2 = new String("2");
123     public static String str3 = new String("3");
124     public static String str4 = new String("4");
125     public static String str5 = new String("5");
126 
127     public static String[] testCloneObjectArray(String[] arr) {
128         return arr.clone();
129     }
130 
131     public static String[] testCloneObjectArrayCopy(String[] arr) {
132         String[] arr2 = new String[arr.length];
133         System.arraycopy(arr, 0, arr2, 0, arr.length);
134         return arr2;
135     }
136 
137     public static String[] testCloneShortObjectArray() {
138         String[] arr = new String[5];
139         arr[0] = str1;
140         arr[1] = str2;
141         arr[2] = str3;
142         arr[3] = str4;
143         arr[4] = str5;
144         escape_arr = arr;
145         return arr.clone();
146     }
147 
148     public static String[] testCloneShortObjectArray2(Method clone) throws Exception {
149         String[] arr = new String[5];
150         arr[0] = str1;
151         arr[1] = str2;
152         arr[2] = str3;
153         arr[3] = str4;
154         arr[4] = str5;
155         escape_arr = arr;
156         return (String[]) testCloneObject(clone, arr);
157     }
158 
159     public static String[] testCloneShortObjectArrayCopy() {
160         String[] arr = new String[5];
161         arr[0] = str1;
162         arr[1] = str2;
163         arr[2] = str3;
164         arr[3] = str4;
165         arr[4] = str5;
166         escape_arr = arr;
167         String[] arr2 = new String[arr.length];
168         System.arraycopy(arr, 0, arr2, 0, arr.length);
169         return arr2;
170     }
171 
172     public static int[] testClonePrimitiveArray(int[] arr) {
173         return arr.clone();
174     }
175 
176     public static Object testCloneOop(Payload p) {
177       return p.clonep();
178     }
179 
180     public static Object testCloneOop2(Payload2 p) {
181         return p.clonep();
182     }
183 
184     public static Object testCloneObject(Method clone, Object obj) throws Exception {
185         return clone.invoke(obj);
186     }
187 
188     public static Object testCloneObjectWithMethodHandle(MethodHandle clone, Object obj) throws Throwable {
189         return clone.invokeExact(obj);
190     }
191 
192     public static void main(String[] args) throws Throwable {
193         Method clone = Object.class.getDeclaredMethod("clone");
194         clone.setAccessible(true);
195 
196         MethodHandles.Lookup privateLookup = MethodHandles.privateLookupIn(Object.class, MethodHandles.lookup());
197         MethodType mt = MethodType.methodType(Object.class);
198         MethodHandle mh = privateLookup.findVirtual(Object.class, "clone", mt);
199 
200         String[] arr1 = new String[42];
201         for (int j = 0; j < arr1.length; j++) {
202             arr1[j] = new String(Integer.toString(j));
203         }
204 
205         for (int i = 0; i < 50_000; i++) {
206             String[] arr2 = testCloneObjectArray(arr1);
207             verifyStr(arr1, arr2);
208             String[] arr3 = testCloneObjectArray(arr1);
209             verifyStr(arr1, arr3);
210             String[] arr4 = testCloneObjectArray(arr1);
211             verifyStr(arr1, arr4);
212             verifyStr(arr1, arr3);
213             verifyStr(arr1, arr2);
214         }
215 
216         for (int i = 0; i < 50_000; i++) {
217             for (int j = 0; j < arr1.length; j++) {
218                 arr1[j] = new String(Integer.toString(j));
219             }
220             String[] arr2 = (String[]) testCloneObject(clone, arr1);
221             verifyStr(arr1, arr2);
222             String[] arr3 = (String[]) testCloneObject(clone, arr1);
223             verifyStr(arr1, arr3);
224             String[] arr4 = (String[]) testCloneObject(clone, arr1);
225             verifyStr(arr1, arr4);
226             verifyStr(arr1, arr3);
227             verifyStr(arr1, arr2);
228         }
229 
230         for (int i = 0; i < 50_000; i++) {
231             String[] value = testCloneShortObjectArray();
232             verifyStr(value, escape_arr);
233             String[] value2 = testCloneShortObjectArray();
234             verifyStr(value2, escape_arr);
235             String[] value3 = testCloneShortObjectArray();
236             verifyStr(value3, escape_arr);
237             String[] value4 = testCloneShortObjectArray2(clone);
238             verifyStr(value4, escape_arr);
239             verifyStr(value, value4);
240             verifyStr(value, value3);
241             verifyStr(value, value2);
242         }
243 
244         for (int i = 0; i < 50_000; i++) {
245             String[] arr2 = testCloneObjectArrayCopy(arr1);
246             verifyStr(arr1, arr2);
247             String[] arr3 = testCloneObjectArrayCopy(arr1);
248             verifyStr(arr1, arr3);
249             String[] arr4 = testCloneObjectArrayCopy(arr1);
250             verifyStr(arr1, arr4);
251             verifyStr(arr1, arr3);
252             verifyStr(arr1, arr2);
253         }
254 
255         for (int i = 0; i < 50_000; i++) {
256             String[] value = testCloneShortObjectArrayCopy();
257             verifyStr(value, escape_arr);
258             String[] value2 = testCloneShortObjectArrayCopy();
259             verifyStr(value2, escape_arr);
260             String[] value3 = testCloneShortObjectArrayCopy();
261             verifyStr(value3, escape_arr);
262             verifyStr(value, value3);
263             verifyStr(value, value2);
264         }
265 
266         for (int i = 0; i < 50_000; i++) {
267             String[] arr2 = (String[]) testCloneObjectWithMethodHandle(mh, (Object)arr1);
268             verifyStr(arr1, arr2);
269             String[] arr3 = (String[]) testCloneObjectWithMethodHandle(mh, (Object)arr1);
270             verifyStr(arr1, arr3);
271             String[] arr4 = (String[]) testCloneObjectWithMethodHandle(mh, (Object)arr1);
272             verifyStr(arr1, arr4);
273             verifyStr(arr1, arr3);
274             verifyStr(arr1, arr2);
275         }
276 
277         int[] arr2 = new int[42];
278         for (int i = 0; i < arr2.length; i++) {
279             arr2[i] = i;
280         }
281         for (int i = 0; i < 50_000; i++) {
282             int[] res1 = testClonePrimitiveArray(arr2);
283             int[] res2 = (int[])testCloneObject(clone, arr2);
284             for (int j = 0; j < arr2.length; j++) {
285                 if (res1[j] != j) {
286                     throw new RuntimeException("Unexpected result: " + res1[j] + " != " + j);
287                 }
288                 if (res2[j] != j) {
289                     throw new RuntimeException("Unexpected result: " + res2[j] + " != " + j);
290                 }
291             }
292         }
293 
294         Payload ref = new Payload(false, -1, 'c', str1, (short) 5, -1);
295         for (int i = 0; i < 50_000; i++) {
296             Payload p1 = (Payload) testCloneOop(ref);
297             verifyPayload(ref, p1);
298             Payload p2 = (Payload) testCloneOop(ref);
299             verifyPayload(ref, p2);
300             Payload p3 = (Payload) testCloneOop(ref);
301             verifyPayload(ref, p3);
302             verifyPayload(p2, p3);
303             verifyPayload(p1, p3);
304         }
305 
306         for (int i = 0; i < 50_000; i++) {
307             Payload p1 = (Payload) testCloneObject(clone, ref);
308             verifyPayload(ref, p1);
309             Payload p2 = (Payload) testCloneObject(clone, ref);
310             verifyPayload(ref, p2);
311             Payload p3 = (Payload) testCloneObject(clone, ref);
312             verifyPayload(ref, p3);
313             verifyPayload(p2, p3);
314             verifyPayload(p1, p3);
315         }
316 
317         Payload2 ref2 = new Payload2(false, -1, 'c', str1, (short) 5, -1, false, 0, 'k', str2, (short)-1, 0);
318         for (int i = 0; i < 50_000; i++) {
319             Payload2 p1 = (Payload2) testCloneOop2(ref2);
320             verifyPayload2(ref2, p1);
321             Payload2 p2 = (Payload2) testCloneOop2(ref2);
322             verifyPayload2(ref2, p2);
323             Payload2 p3 = (Payload2) testCloneOop2(ref2);
324             verifyPayload2(ref2, p3);
325             verifyPayload2(p2, p3);
326             verifyPayload2(p1, p3);
327         }
328 
329         for (int i = 0; i < 50_000; i++) {
330             Payload2 p1 = (Payload2) testCloneObject(clone, ref2);
331             verifyPayload2(ref2, p1);
332             Payload2 p2 = (Payload2) testCloneObject(clone, ref2);
333             verifyPayload2(ref2, p2);
334             Payload2 p3 = (Payload2) testCloneObject(clone, ref2);
335             verifyPayload2(ref2, p3);
336             verifyPayload2(p2, p3);
337             verifyPayload2(p1, p3);
338         }
339 
340         for (int i = 0; i < 50_000; i++) {
341             Payload2 p1 = (Payload2) testCloneObjectWithMethodHandle(mh, ref2);
342             verifyPayload2(ref2, p1);
343             Payload2 p2 = (Payload2) testCloneObjectWithMethodHandle(mh, ref2);
344             verifyPayload2(ref2, p2);
345             Payload2 p3 = (Payload2) testCloneObjectWithMethodHandle(mh, ref2);
346             verifyPayload2(ref2, p3);
347             verifyPayload2(p2, p3);
348             verifyPayload2(p1, p3);
349         }
350     }
351 
352     public static void verifyPayload(Payload p1, Payload p2) {
353         if  (p1.b != p2.b) {
354             throw new RuntimeException("b is wrong");
355         }
356         if  (p1.c != p2.c) {
357             throw new RuntimeException("c is wrong");
358         }
359         if  (p1.i != p2.i) {
360             throw new RuntimeException("i is wrong");
361         }
362         if  (p1.s != p2.s) {
363             throw new RuntimeException("s is wrong");
364         }
365         if  (p1.i2 != p2.i2) {
366             throw new RuntimeException("i2 is wrong");
367         }
368         if  (p1.str != p2.str) {
369             throw new RuntimeException("str is wrong");
370         }
371         if  (!p1.str.equals(p2.str)) {
372             throw new RuntimeException("str content is wrong");
373         }
374     }
375 
376     public static void verifyPayload2(Payload2 p1, Payload2 p2) {
377         if  (p1.b != p2.b) {
378             throw new RuntimeException("b is wrong");
379         }
380         if  (p1.c != p2.c) {
381             throw new RuntimeException("c is wrong");
382         }
383         if  (p1.i != p2.i) {
384             throw new RuntimeException("i is wrong");
385         }
386         if  (p1.s != p2.s) {
387             throw new RuntimeException("s is wrong");
388         }
389         if  (p1.i2 != p2.i2) {
390             throw new RuntimeException("i2 is wrong");
391         }
392         if  (p1.str != p2.str) {
393             throw new RuntimeException("str is wrong");
394         }
395         if  (!p1.str.equals(p2.str)) {
396             throw new RuntimeException("str content is wrong");
397         }
398         if  (p1.b2 != p2.b2) {
399             throw new RuntimeException("b is wrong");
400         }
401         if  (p1.c2 != p2.c2) {
402             throw new RuntimeException("c is wrong");
403         }
404         if  (p1.i3 != p2.i3) {
405             throw new RuntimeException("i is wrong");
406         }
407         if  (p1.s2 != p2.s2) {
408             throw new RuntimeException("s is wrong");
409         }
410         if  (p1.i4 != p2.i4) {
411             throw new RuntimeException("i2 is wrong");
412         }
413         if  (p1.str2 != p2.str2) {
414             throw new RuntimeException("str is wrong");
415         }
416         if  (!p1.str2.equals(p2.str2)) {
417             throw new RuntimeException("str content is wrong");
418         }
419     }
420 
421     public static void verifyStr(String[] arr1, String[] arr2) {
422         if (arr1 == arr2) {
423             throw new RuntimeException("Must not be the same");
424         }
425         if (arr1.length != arr2.length) {
426             throw new RuntimeException("Must have the same length");
427         }
428         for (int i = 0; i < arr1.length; i++) {
429             if (arr1[i] != arr2[i]) {
430                 throw new RuntimeException("Fail cloned element not the same: " + i);
431             }
432             if (!arr1[i].equals(arr2[i])) {
433                 throw new RuntimeException("Fail cloned element content not the same");
434             }
435         }
436     }
437 }
438