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