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 import jdk.internal.misc.Unsafe;
25 import java.lang.reflect.Field;
26
27 /*
28 * @test
29 * @summary Test Unsafe.copySwapMemory
30 * @modules java.base/jdk.internal.misc
31 */
32 public class CopySwap {
33 private static final boolean DEBUG = Boolean.getBoolean("CopySwap.DEBUG");
34
35 public static final long KB = 1024;
36 public static final long MB = KB * 1024;
37 public static final long GB = MB * 1024;
38
39 private static final Unsafe UNSAFE;
40 private static final int SMALL_COPY_SIZE = 32;
41 private static final int BASE_ALIGNMENT = 16;
42
43 static {
44 try {
45 Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
46 f.setAccessible(true);
47 UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
48 } catch (Exception e) {
49 throw new RuntimeException("Unable to get Unsafe instance.", e);
50 }
51 }
52
53 private static long alignDown(long value, long alignment) {
54 return value & ~(alignment - 1);
55 }
56
57 private static long alignUp(long value, long alignment) {
58 return (value + alignment - 1) & ~(alignment - 1);
59 }
60
61 private static boolean isAligned(long value, long alignment) {
62 return value == alignDown(value, alignment);
63 }
64
65 private CopySwap() {
66 }
67
68 /**
69 * Generate verification data for a given offset
70 *
71 * The verification data is used to verify that the correct bytes
72 * have indeed been copied and byte swapped.
73 *
74 * The data is generated based on the offset (in bytes) into the
75 * source buffer. For a native buffer the offset is relative to
76 * the base pointer. For a heap array it is relative to the
77 * address of the first array element.
78 *
79 * This method will return the result of doing an elementSize byte
80 * read starting at offset (in bytes).
81 *
82 * @param offset offset into buffer
83 * @param elemSize size (in bytes) of the element
84 *
85 * @return the verification data, only the least significant
86 * elemSize*8 bits are set, zero extended
87 */
88 private long getVerificationDataForOffset(long offset, long elemSize) {
89 byte[] bytes = new byte[(int)elemSize];
90
91 for (long i = 0; i < elemSize; i++) {
92 bytes[(int)i] = (byte)(offset + i);
93 }
94
95 long o = UNSAFE.arrayBaseOffset(byte[].class);
96
97 switch ((int)elemSize) {
98 case 1: return Byte.toUnsignedLong(UNSAFE.getByte(bytes, o));
99 case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(bytes, o));
100 case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(bytes, o));
101 case 8: return UNSAFE.getLongUnaligned(bytes, o);
102 default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
103 }
104 }
105
106 /**
107 * Verify byte swapped data
108 *
109 * @param ptr the data to verify
110 * @param srcOffset the srcOffset (in bytes) from which the copy started,
111 * used as key to regenerate the verification data
112 * @param dstOffset the offset (in bytes) in the array at which to start
113 * the verification, relative to the first element in the array
114 * @param size size (in bytes) of data to to verify
115 * @param elemSize size (in bytes) of the individual array elements
116 *
117 * @throws RuntimeException if an error is found
118 */
119 private void verifySwappedData(GenericPointer ptr, long srcOffset, long dstOffset, long size, long elemSize) {
120 for (long offset = 0; offset < size; offset += elemSize) {
121 long expectedUnswapped = getVerificationDataForOffset(srcOffset + offset, elemSize);
122 long expected = byteSwap(expectedUnswapped, elemSize);
123
124 long actual = getArrayElem(ptr, dstOffset + offset, elemSize);
125
126 if (expected != actual) {
127 throw new RuntimeException("srcOffset: 0x" + Long.toHexString(srcOffset) +
128 " dstOffset: 0x" + Long.toHexString(dstOffset) +
129 " size: 0x" + Long.toHexString(size) +
130 " offset: 0x" + Long.toHexString(offset) +
131 " expectedUnswapped: 0x" + Long.toHexString(expectedUnswapped) +
132 " expected: 0x" + Long.toHexString(expected) +
133 " != actual: 0x" + Long.toHexString(actual));
134 }
135 }
136 }
137
138 /**
139 * Initialize an array with verification friendly data
140 *
141 * @param ptr pointer to the data to initialize
142 * @param size size (in bytes) of the data
143 * @param elemSize size (in bytes) of the individual elements
144 */
145 private void initVerificationData(GenericPointer ptr, long size, long elemSize) {
146 for (long offset = 0; offset < size; offset++) {
147 byte data = (byte)getVerificationDataForOffset(offset, 1);
148
149 if (ptr.isOnHeap()) {
150 UNSAFE.putByte(ptr.getObject(), ptr.getOffset() + offset, data);
151 } else {
152 UNSAFE.putByte(ptr.getOffset() + offset, data);
153 }
154 }
155 }
156
157 /**
158 * Allocate a primitive array
159 *
160 * @param size size (in bytes) of all the array elements (elemSize * length)
161 * @param elemSize the size of the array elements
162 *
163 * @return a newly allocated primitive array
164 */
165 Object allocArray(long size, long elemSize) {
166 int length = (int)(size / elemSize);
167
168 switch ((int)elemSize) {
169 case 2: return new short[length];
170 case 4: return new int[length];
171 case 8: return new long[length];
172 default:
173 throw new IllegalArgumentException("Invalid element size: " + elemSize);
174 }
175 }
176
177 /**
178 * Get the value of a primitive array entry
179 *
180 * @param ptr pointer to the data
181 * @param offset offset (in bytes) of the array element, relative to the first element in the array
182 *
183 * @return the array element, as an unsigned long
184 */
185 private long getArrayElem(GenericPointer ptr, long offset, long elemSize) {
186 if (ptr.isOnHeap()) {
187 Object o = ptr.getObject();
188 int index = (int)(offset / elemSize);
189
190 if (o instanceof short[]) {
191 short[] arr = (short[])o;
192 return Short.toUnsignedLong(arr[index]);
193 } else if (o instanceof int[]) {
194 int[] arr = (int[])o;
195 return Integer.toUnsignedLong(arr[index]);
196 } else if (o instanceof long[]) {
197 long[] arr = (long[])o;
198 return arr[index];
199 } else {
200 throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName());
201 }
202 } else {
203 long addr = ptr.getOffset() + offset;
204
205 switch ((int)elemSize) {
206 case 1: return Byte.toUnsignedLong(UNSAFE.getByte(addr));
207 case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(null, addr));
208 case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(null, addr));
209 case 8: return UNSAFE.getLongUnaligned(null, addr);
210 default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
211 }
212 }
213 }
214
215 private void putValue(long addr, long elemSize, long value) {
216 switch ((int)elemSize) {
217 case 1: UNSAFE.putByte(addr, (byte)value); break;
218 case 2: UNSAFE.putShortUnaligned(null, addr, (short)value); break;
219 case 4: UNSAFE.putIntUnaligned(null, addr, (int)value); break;
220 case 8: UNSAFE.putLongUnaligned(null, addr, value); break;
221 default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
222 }
223 }
224
225 /**
226 * Get the size of the elements for an array
227 *
228 * @param o a primitive heap array
229 *
230 * @return the size (in bytes) of the individual array elements
231 */
232 private long getArrayElemSize(Object o) {
233 if (o instanceof short[]) {
234 return 2;
235 } else if (o instanceof int[]) {
236 return 4;
237 } else if (o instanceof long[]) {
238 return 8;
239 } else {
240 throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName());
241 }
242 }
243
244 /**
245 * Byte swap a value
246 *
247 * @param value the value to swap, only the bytes*8 least significant bits are used
248 * @param size size (in bytes) of the value
249 *
250 * @return the byte swapped value in the bytes*8 least significant bits
251 */
252 private long byteSwap(long value, long size) {
253 switch ((int)size) {
254 case 2: return Short.toUnsignedLong(Short.reverseBytes((short)value));
255 case 4: return Integer.toUnsignedLong(Integer.reverseBytes((int)value));
256 case 8: return Long.reverseBytes(value);
257 default: throw new IllegalArgumentException("Invalid element size: " + size);
258 }
259 }
260
261 /**
262 * Verify data in a heap array which has *not* been byte swapped
263 *
264 * @param ptr the data to verify
265 * @param startOffset the offset (in bytes) at which to start the verification
266 * @param size size (in bytes) of the data to verify
267 *
268 * @throws RuntimeException if an error is found
269 */
270 private void verifyUnswappedData(GenericPointer ptr, long startOffset, long size) {
271 for (long elemOffset = startOffset; elemOffset < startOffset + size; elemOffset++) {
272 byte expected = (byte)getVerificationDataForOffset(elemOffset, 1);
273
274 byte actual;
275 if (ptr.isOnHeap()) {
276 actual = UNSAFE.getByte(ptr.getObject(), ptr.getOffset() + elemOffset);
277 } else {
278 actual = UNSAFE.getByte(ptr.getOffset() + elemOffset);
279 }
280
281 if (expected != actual) {
282 throw new RuntimeException("startOffset: 0x" + Long.toHexString(startOffset) +
283 " size: 0x" + Long.toHexString(size) +
284 " elemOffset: 0x" + Long.toHexString(elemOffset) +
285 " expected: 0x" + Long.toHexString(expected) +
286 " != actual: 0x" + Long.toHexString(actual));
287 }
288 }
289 }
290
291
292 /**
293 * Copy and byte swap data from the source to the destination
294 *
295 * This method will pre-populate the whole source and destination
296 * buffers with verification friendly data. It will then use
297 * copySwapMemory to fill part of the destination buffer with
298 * swapped data from the source. Some space (padding) will be
299 * left before and after the data in the destination buffer, which
300 * should not be touched/overwritten by the copy call.
301 *
302 * Note: Both source and destination buffers will be overwritten!
303 *
304 * @param src source buffer to copy from
305 * @param srcOffset the offset (in bytes) in the source buffer, relative to
306 * the first array element, at which to start reading data
307 * @param dst destination buffer to copy to
308 * @param dstOffset the offset (in bytes) in the destination
309 * buffer, relative to the first array element, at which to
310 * start writing data
311 * @param bufSize the size (in bytes) of the src and dst arrays
312 * @param copyBytes the size (in bytes) of the copy to perform,
313 * must be a multiple of elemSize
314 * @param elemSize the size (in bytes) of the elements to byte swap
315 *
316 * @throws RuntimeException if an error is found
317 */
318 private void testCopySwap(GenericPointer src, long srcOffset,
319 GenericPointer dst, long dstOffset,
320 long bufSize, long copyBytes, long elemSize) {
321 if (!isAligned(copyBytes, elemSize)) {
322 throw new IllegalArgumentException(
323 "copyBytes (" + copyBytes + ") must be a multiple of elemSize (" + elemSize + ")");
324 }
325 if (src.isOnHeap() && !isAligned(srcOffset, elemSize)) {
326 throw new IllegalArgumentException(
327 "srcOffset (" + srcOffset + ") must be a multiple of elemSize (" + elemSize + ")");
328 }
329 if (dst.isOnHeap() && !isAligned(dstOffset, elemSize)) {
330 throw new IllegalArgumentException(
331 "dstOffset (" + dstOffset + ") must be a multiple of elemSize (" + elemSize + ")");
332 }
333 if (srcOffset + copyBytes > bufSize) {
334 throw new IllegalArgumentException(
335 "srcOffset (" + srcOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")");
336 }
337 if (dstOffset + copyBytes > bufSize) {
338 throw new IllegalArgumentException(
339 "dstOffset (" + dstOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")");
340 }
341
342 // Initialize the whole source buffer with a verification friendly pattern (no 0x00 bytes)
343 initVerificationData(src, bufSize, elemSize);
344 if (!src.equals(dst)) {
345 initVerificationData(dst, bufSize, elemSize);
346 }
347
348 if (DEBUG) {
349 System.out.println("===before===");
350 for (int offset = 0; offset < bufSize; offset += elemSize) {
351 long srcValue = getArrayElem(src, offset, elemSize);
352 long dstValue = getArrayElem(dst, offset, elemSize);
353
354 System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) +
355 " src=0x" + Long.toHexString(srcValue) +
356 " dst=0x" + Long.toHexString(dstValue));
357 }
358 }
359
360 // Copy & swap data into the middle of the destination buffer
361 UNSAFE.copySwapMemory(src.getObject(),
362 src.getOffset() + srcOffset,
363 dst.getObject(),
364 dst.getOffset() + dstOffset,
365 copyBytes,
366 elemSize);
367
368 if (DEBUG) {
369 System.out.println("===after===");
370 for (int offset = 0; offset < bufSize; offset += elemSize) {
371 long srcValue = getArrayElem(src, offset, elemSize);
372 long dstValue = getArrayElem(dst, offset, elemSize);
373
374 System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) +
375 " src=0x" + Long.toHexString(srcValue) +
376 " dst=0x" + Long.toHexString(dstValue));
377 }
378 }
379
380 // Verify the the front padding is unchanged
381 verifyUnswappedData(dst, 0, dstOffset);
382
383 // Verify swapped data
384 verifySwappedData(dst, srcOffset, dstOffset, copyBytes, elemSize);
385
386 // Verify that the back back padding is unchanged
387 long frontAndDataBytes = dstOffset + copyBytes;
388 long trailingBytes = bufSize - frontAndDataBytes;
389 verifyUnswappedData(dst, frontAndDataBytes, trailingBytes);
390 }
391
392 /**
393 * Test various configurations copy-swapping from one buffer to the other
394 *
395 * @param src the source buffer to copy from
396 * @param dst the destination buffer to copy to
397 * @param size size (in bytes) of the buffers
398 * @param elemSize size (in bytes) of the individual elements
399 *
400 * @throws RuntimeException if an error is found
401 */
402 public void testBufferPair(GenericPointer src, GenericPointer dst, long size, long elemSize) {
403 // offset in source from which to start reading data
404 for (long srcOffset = 0; srcOffset < size; srcOffset += (src.isOnHeap() ? elemSize : 1)) {
405
406 // offset in destination at which to start writing data
407 for (int dstOffset = 0; dstOffset < size; dstOffset += (dst.isOnHeap() ? elemSize : 1)) {
408
409 // number of bytes to copy
410 long maxCopyBytes = Math.min(size - srcOffset, size - dstOffset);
411 for (long copyBytes = 0; copyBytes < maxCopyBytes; copyBytes += elemSize) {
412 try {
413 testCopySwap(src, srcOffset, dst, dstOffset, size, copyBytes, elemSize);
414 } catch (RuntimeException e) {
415 // Wrap the exception in another exception to catch the relevant configuration data
416 throw new RuntimeException("testBufferPair: " +
417 "src=" + src +
418 " dst=" + dst +
419 " elemSize=0x" + Long.toHexString(elemSize) +
420 " copyBytes=0x" + Long.toHexString(copyBytes) +
421 " srcOffset=0x" + Long.toHexString(srcOffset) +
422 " dstOffset=0x" + Long.toHexString(dstOffset),
423 e);
424 }
425 }
426 }
427 }
428 }
429
430 /**
431 * Test copying between various permutations of buffers
432 *
433 * @param buffers buffers to permute (src x dst)
434 * @param size size (in bytes) of buffers
435 * @param elemSize size (in bytes) of individual elements
436 *
437 * @throws RuntimeException if an error is found
438 */
439 public void testPermuteBuffers(GenericPointer[] buffers, long size, long elemSize) {
440 for (int srcIndex = 0; srcIndex < buffers.length; srcIndex++) {
441 for (int dstIndex = 0; dstIndex < buffers.length; dstIndex++) {
442 testBufferPair(buffers[srcIndex], buffers[dstIndex], size, elemSize);
443 }
444 }
445 }
446
447 /**
448 * Test copying of a specific element size
449 *
450 * @param size size (in bytes) of buffers to allocate
451 * @param elemSize size (in bytes) of individual elements
452 *
453 * @throws RuntimeException if an error is found
454 */
455 private void testElemSize(long size, long elemSize) {
456 long buf1Raw = 0;
457 long buf2Raw = 0;
458
459 try {
460 buf1Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
461 long buf1 = alignUp(buf1Raw, BASE_ALIGNMENT);
462
463 buf2Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
464 long buf2 = alignUp(buf2Raw, BASE_ALIGNMENT);
465
466 GenericPointer[] buffers = {
467 new GenericPointer(buf1),
468 new GenericPointer(buf2),
469 new GenericPointer(allocArray(size, elemSize)),
470 new GenericPointer(allocArray(size, elemSize))
471 };
472
473 testPermuteBuffers(buffers, size, elemSize);
474 } finally {
475 if (buf1Raw != 0) {
476 UNSAFE.freeMemory(buf1Raw);
477 }
478 if (buf2Raw != 0) {
479 UNSAFE.freeMemory(buf2Raw);
480 }
481 }
482 }
483
484 /**
485 * Verify that small copy swaps work
486 */
487 private void testSmallCopy() {
488 int smallBufSize = SMALL_COPY_SIZE;
489
490 // Test various element types and heap/native combinations
491 for (long elemSize = 2; elemSize <= 8; elemSize <<= 1) {
492 testElemSize(smallBufSize, elemSize);
493 }
494 }
495
496
497 /**
498 * Verify that large copy swaps work
499 */
500 private void testLargeCopy() {
501 long size = 2 * GB + 8;
502 long bufRaw = 0;
503
504 // Check that a large native copy succeeds
505 try {
506 try {
507 bufRaw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
508 } catch (OutOfMemoryError e) {
509 // Accept failure, skip test
510 return;
511 }
512
513 long buf = alignUp(bufRaw, BASE_ALIGNMENT);
514
515 UNSAFE.copySwapMemory(null, buf, null, buf, size, 8);
516 } catch (Exception e) {
517 throw new RuntimeException("copySwapMemory of large buffer failed");
518 } finally {
519 if (bufRaw != 0) {
520 UNSAFE.freeMemory(bufRaw);
521 }
522 }
523 }
524
525 /**
526 * Run positive tests
527 *
528 * @throws RuntimeException if an error is found
529 */
530 private void testPositive() {
531 testSmallCopy();
532 testLargeCopy();
533 }
534
535 /**
536 * Run negative tests, testing corner cases and the various exceptions
537 *
538 * @throws RuntimeException if an error is found
539 */
540 private void testNegative() {
541 long bufRaw = 0;
542
543 try {
544 bufRaw = UNSAFE.allocateMemory(1024);
545 long buf = alignUp(bufRaw, BASE_ALIGNMENT);
546 short[] arr = new short[16];
547
548 // Check various illegal element sizes
549 for (int elemSize = 2; elemSize <= 8; elemSize <<= 1) {
550 long[] illegalSizes = { -1, 1, elemSize - 1, elemSize + 1, elemSize * 2 - 1 };
551 for (long size : illegalSizes) {
552 try {
553 // Check that illegal elemSize throws an IAE
554 UNSAFE.copySwapMemory(null, buf, null, buf, size, elemSize);
555 throw new RuntimeException("copySwapMemory failed to throw IAE for size=" + size + " elemSize=" + elemSize);
556 } catch (IllegalArgumentException e) {
557 // good
558 }
559 }
560 }
561
562 try {
563 // Check that negative srcOffset throws an IAE
564 UNSAFE.copySwapMemory(arr, -1, arr, UNSAFE.arrayBaseOffset(arr.getClass()), 16, 2);
565 throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset=-1");
619 } finally {
620 if (bufRaw != 0) {
621 UNSAFE.freeMemory(bufRaw);
622 }
623 }
624 }
625
626 /**
627 * Run all tests
628 *
629 * @throws RuntimeException if an error is found
630 */
631 private void test() {
632 testPositive();
633 testNegative();
634 }
635
636 public static void main(String[] args) {
637 CopySwap cs = new CopySwap();
638 cs.test();
639 }
640
641 /**
642 * Helper class to represent a "pointer" - either a heap array or
643 * a pointer to a native buffer.
644 *
645 * In the case of a native pointer, the Object is null and the offset is
646 * the absolute address of the native buffer.
647 *
648 * In the case of a heap object, the Object is a primitive array, and
649 * the offset will be set to the base offset to the first element, meaning
650 * the object and the offset together form a double-register pointer.
651 */
652 static class GenericPointer {
653 private final Object o;
654 private final long offset;
655
656 private GenericPointer(Object o, long offset) {
657 this.o = o;
658 this.offset = offset;
659 }
660
661 public String toString() {
662 return "GenericPointer(o={" + o + "}, offset=0x" + Long.toHexString(offset) + ")";
663 }
664
665 public boolean equals(Object other) {
666 if (!(other instanceof GenericPointer)) {
667 return false;
668 }
669
670 GenericPointer otherp = (GenericPointer)other;
671
672 return o == otherp.o && offset == otherp.offset;
673 }
674
675 GenericPointer(Object o) {
676 this(o, UNSAFE.arrayBaseOffset(o.getClass()));
677 }
678
679 GenericPointer(long offset) {
680 this(null, offset);
681 }
682
683 public boolean isOnHeap() {
684 return o != null;
685 }
686
687 public Object getObject() {
688 return o;
689 }
690
691 public long getOffset() {
692 return offset;
693 }
694 }
695 }
|
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 import jdk.internal.misc.Unsafe;
25 import java.lang.reflect.Field;
26
27 /*
28 * @test
29 * @summary Test Unsafe.copySwapMemory
30 * @modules java.base/jdk.internal.misc
31 */
32 public class CopySwap {
33 private static final Unsafe UNSAFE;
34
35 static {
36 try {
37 Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
38 f.setAccessible(true);
39 UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
40 } catch (Exception e) {
41 throw new RuntimeException("Unable to get Unsafe instance.", e);
42 }
43 }
44
45 private CopySwap() {
46 }
47
48 /**
49 * Run positive tests
50 *
51 * @throws RuntimeException if an error is found
52 */
53 private void testPositive() {
54 CopyCommon cc = new CopyCommon();
55 cc.testSmallCopy(true);
56 cc.testLargeCopy(true);
57 }
58
59 /**
60 * Run negative tests, testing corner cases and the various exceptions
61 *
62 * @throws RuntimeException if an error is found
63 */
64 private void testNegative() {
65 long bufRaw = 0;
66
67 try {
68 bufRaw = UNSAFE.allocateMemory(1024);
69 long buf = CopyCommon.alignUp(bufRaw, CopyCommon.BASE_ALIGNMENT);
70 short[] arr = new short[16];
71
72 // Check various illegal element sizes
73 for (int elemSize = 2; elemSize <= 8; elemSize <<= 1) {
74 long[] illegalSizes = { -1, 1, elemSize - 1, elemSize + 1, elemSize * 2 - 1 };
75 for (long size : illegalSizes) {
76 try {
77 // Check that illegal elemSize throws an IAE
78 UNSAFE.copySwapMemory(null, buf, null, buf, size, elemSize);
79 throw new RuntimeException("copySwapMemory failed to throw IAE for size=" + size + " elemSize=" + elemSize);
80 } catch (IllegalArgumentException e) {
81 // good
82 }
83 }
84 }
85
86 try {
87 // Check that negative srcOffset throws an IAE
88 UNSAFE.copySwapMemory(arr, -1, arr, UNSAFE.arrayBaseOffset(arr.getClass()), 16, 2);
89 throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset=-1");
143 } finally {
144 if (bufRaw != 0) {
145 UNSAFE.freeMemory(bufRaw);
146 }
147 }
148 }
149
150 /**
151 * Run all tests
152 *
153 * @throws RuntimeException if an error is found
154 */
155 private void test() {
156 testPositive();
157 testNegative();
158 }
159
160 public static void main(String[] args) {
161 CopySwap cs = new CopySwap();
162 cs.test();
163 }
164 }
|