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