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