1 /*
   2  * Copyright (c) 2019, 2019, 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 import jdk.test.lib.Asserts;
  26 
  27 import java.lang.reflect.*;
  28 import java.util.Random;
  29 import java.util.Arrays;
  30 import java.util.Comparator;
  31 
  32 import jdk.internal.misc.Unsafe;
  33 
  34 /*
  35  * @test
  36  * @summary Test flattened arrays accesses through JNI
  37  * @modules java.base/jdk.internal.misc
  38  * @library /testlibrary /test/lib
  39  * @requires (os.simpleArch == "x64")
  40  * @requires (os.family == "linux" | os.family == "mac")
  41  * @compile -XDallowGenericsOverValues -XDallowWithFieldOperator TestJNIArrays.java
  42  * @run main/othervm/native/timeout=3000 -XX:ValueArrayElemMaxFlatSize=128 TestJNIArrays
  43  */
  44 
  45 public class TestJNIArrays {
  46 
  47     static final Unsafe U = Unsafe.getUnsafe();
  48     
  49     public static final int ARRAY_SIZE = 1024;
  50     static long seed;
  51     static Random random;
  52 
  53     static {
  54         seed = System.nanoTime();
  55         System.out.println("Seed = " + seed); 
  56         random = new Random(seed);
  57     }
  58 
  59     static {
  60         System.loadLibrary("TestJNIArrays");
  61     }
  62 
  63     static inline class IntInt {
  64         int i0;
  65         int i1;
  66 
  67         public IntInt(int i0, int i1) {
  68             this.i0 = i0;
  69             this.i1 = i1;
  70         }
  71     }
  72 
  73     static class IntIntComparator implements Comparator<IntInt> {
  74         public int compare(IntInt a, IntInt b) {
  75             if (a.i0 < b.i0) return -1;
  76             if (a.i0 > b.i0) return 1;
  77             if (a.i1 < b.i1) return -1;
  78             if (a.i1 > b.i1) return 1;
  79             return 0;
  80         }
  81     }
  82 
  83     static inline class Containee {
  84         float f;
  85         short s;
  86 
  87         Containee(float f, short s) {
  88             this.f = f;
  89             this.s = s;
  90         }
  91     }
  92     
  93     static inline class Container {
  94         double d;
  95         Containee c;
  96         byte b;
  97 
  98         Container(double d, Containee c, byte b) {
  99             this.d = d ;
 100             this.c = c;
 101             this.b = b;
 102         }
 103 
 104         Container setc(Containee c) {
 105             Container res = __WithField(this.c, c);
 106             return res;
 107         }
 108 
 109     }
 110 
 111     static inline class LongLongLongLong {
 112         long l0, l1, l2, l3;
 113 
 114         public LongLongLongLong(long l0, long l1, long l2, long l3) {
 115             this.l0 = l0;
 116             this.l1 = l1;
 117             this.l2 = l2;
 118             this.l3 = l3;
 119         }
 120     }
 121 
 122     static inline class BigValue {
 123         long l0 = 0, l1 = 0,   l2 = 0, l3 = 0, l4 = 0, l5 = 0, l6 = 0, l7 = 0, l8 = 0, l9 = 0;
 124         long l10 = 0, l11 = 0, l12 = 0, l13 = 0, l14 = 0, l15 = 0, l16 = 0, l17 = 0, l18 = 0, l19 = 0;
 125         long l20 = 0, l21 = 0, l22 = 0, l23 = 0, l24 = 0, l25 = 0, l26 = 0, l27 = 0, l28 = 0, l29 = 0;
 126         long l30 = 0, l31 = 0, l32 = 0, l33 = 0, l34 = 0, l35 = 0, l36 = 0, l37 = 0, l38 = 0, l39 = 0;
 127     }
 128 
 129     static inline class ValueWithOops {
 130         String o = null;
 131         int i = 0;
 132     }
 133     
 134     public static void main(String[] args) {
 135         TestJNIArrays test = new TestJNIArrays();
 136         test.checkGetFlattenedArrayElementSize();
 137         test.checkGetFlattenedArrayElementClass();
 138         test.checkGetFieldOffsetInFlattenedLayout();
 139         test.checkGetFlattenedArrayElements();
 140         test.checkBehaviors();
 141         // test.mesureInitializationTime(1024 * 1024 * 10 , 1000);
 142         // test.mesureInitializationTime2(1024 * 1024 * 10 , 1000);
 143         // test.mesureUpdateTime2(1024 * 1024 * 10, 1000);
 144         // test.mesureSortingTime(1024 * 1024, 100); // reduced number of iterations because Java sorting is slow (because of generics?)
 145         test.mesureInitializationTime3(1024 * 1024 * 2 , 1000);
 146     }
 147 
 148     void checkGetFlattenedArrayElementSize() {
 149         Throwable exception = null;
 150         try {
 151             Object o = new Object();
 152             GetFlattenedArrayElementSizeWrapper(o);
 153         } catch(Throwable t) {
 154             exception = t;
 155         }
 156         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 157         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 158         exception = null;
 159         try {
 160             int[] array = new int[16];
 161             Object o = array;
 162             GetFlattenedArrayElementSizeWrapper(o);
 163         } catch(Throwable t) {
 164             exception = t;
 165         }
 166         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 167         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 168         exception = null;
 169         try {
 170             GetFlattenedArrayElementSizeWrapper(new String[16]);
 171         } catch(Throwable t) {
 172             exception = t;
 173         }
 174         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 175         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 176         exception = null;
 177         try {
 178             // Array of BigValue should not be flattened because BigValue is *big*
 179             GetFlattenedArrayElementSizeWrapper(new BigValue[16]);
 180         } catch(Throwable t) {
 181             exception = t;
 182         }
 183         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 184         Asserts.assertTrue(exception instanceof IllegalArgumentException , "Exception should be a IAE");
 185         exception = null;
 186         int size = -1;
 187         try {
 188             size = GetFlattenedArrayElementSizeWrapper(new IntInt[16]);
 189         } catch(Throwable t) {
 190             exception = t;
 191         }
 192         Asserts.assertNull(exception, "No exception should have been thrown");
 193         Asserts.assertEquals(size, 8, "Wrong size");
 194     }
 195 
 196     void checkGetFlattenedArrayElementClass() {
 197         Throwable exception = null;
 198         try {
 199             Object o = new Object();
 200             GetFlattenedArrayElementClassWrapper(o);
 201         } catch(Throwable t) {
 202             exception = t;
 203         }
 204         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 205         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 206         exception = null;
 207         try {
 208             int[] array = new int[16];
 209             Object o = array;
 210             GetFlattenedArrayElementClassWrapper(o);
 211         } catch(Throwable t) {
 212             exception = t;
 213         }
 214         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 215         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 216         exception = null;
 217         try {
 218             GetFlattenedArrayElementClassWrapper(new String[16]);
 219         } catch(Throwable t) {
 220             exception = t;
 221         }
 222         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 223         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 224         exception = null;
 225         try {
 226             // Array of BigValue should not be flattened because BigValue is *big*
 227             GetFlattenedArrayElementClassWrapper(new BigValue[16]);
 228         } catch(Throwable t) {
 229             exception = t;
 230         }
 231         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 232         Asserts.assertTrue(exception instanceof IllegalArgumentException , "Exception should be a IAE");
 233         exception = null;
 234         Class c = null;
 235         try {
 236             c = GetFlattenedArrayElementClassWrapper(new IntInt[16]);
 237         } catch(Throwable t) {
 238             exception = t;
 239         }
 240         Asserts.assertNull(exception, "No exception should have been thrown");
 241         Asserts.assertEquals(c, IntInt.class, "Wrong class");
 242     }
 243 
 244     void checkGetFieldOffsetInFlattenedLayout() {
 245         Throwable exception = null;
 246         try {
 247             Object o = new Object();
 248             GetFieldOffsetInFlattenedLayoutWrapper(o.getClass(), "foo", "I", true);
 249         } catch(Throwable t) {
 250             exception = t;
 251         }
 252         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 253         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 254         exception = null;
 255         try {
 256             int[] array = new int[16];
 257             GetFieldOffsetInFlattenedLayoutWrapper(array.getClass(), "foo", "I", true);
 258         } catch(Throwable t) {
 259             exception = t;
 260         }
 261         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 262         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 263         exception = null;
 264         try {
 265             String[] array = new String[16];
 266             GetFieldOffsetInFlattenedLayoutWrapper(array.getClass(), "foo", "I", true);
 267         } catch(Throwable t) {
 268             exception = t;
 269         }
 270         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 271         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 272         exception = null;
 273         Containee ce  = new Containee(3.4f, (short)5);
 274         Container c = new Container(123.876, ce, (byte)7);
 275         Class<?> cclass = c.getClass();
 276         Container[] containerArray = new Container[32];
 277         int elementSize = GetFlattenedArrayElementSizeWrapper(containerArray);
 278         int offset = -1;
 279         try {
 280             offset = GetFieldOffsetInFlattenedLayoutWrapper(cclass, "d", "D", false);
 281         } catch(Throwable t) {
 282             exception = t;
 283         }
 284         Asserts.assertNull(exception, "No exception should have been thrown");
 285         Field f = null;
 286         try {
 287             f = cclass.getDeclaredField("d");
 288         } catch(NoSuchFieldException e) {
 289             e.printStackTrace();
 290             return;
 291         }
 292         Asserts.assertEquals(U.valueHeaderSize(cclass) + offset, U.objectFieldOffset(cclass, f.getName()),
 293                              "Incorrect offset");
 294         Asserts.assertLessThan(offset, elementSize, "Invalid offset");
 295         exception = null;
 296         try {
 297             // Field c should be flattened, so last argument is true, no exception expected
 298             GetFieldOffsetInFlattenedLayoutWrapper(cclass, "c", "QTestJNIArrays$Containee;", true);
 299         } catch(Throwable t) {
 300             exception = t;
 301         }
 302         Asserts.assertNull(exception, "No exception should have been thrown");
 303         Asserts.assertLessThan(offset, elementSize, "Invalid offset");
 304         exception = null;
 305         try {
 306             // Field c should be flattened, with last argument being false, exception expected from the wrapper 
 307             GetFieldOffsetInFlattenedLayoutWrapper(cclass, "c", "QTestJNIArrays$Containee;", false);
 308         } catch(Throwable t) {
 309             exception = t;
 310         }
 311         Asserts.assertNotNull(exception, "Wrapper should have thrown a RuntimeException");
 312         Asserts.assertEquals(exception.getClass(), RuntimeException.class , "Wrong exception type");
 313     }
 314     
 315      void checkGetFlattenedArrayElements() {
 316         Throwable exception = null;
 317         Object o = new Object();
 318         try {
 319             GetFlattenedArrayElementsWrapper(o);
 320         } catch(Throwable t) {
 321             exception = t;
 322         }
 323         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 324         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 325         exception = null;
 326         int[] a1 = new int[16];
 327         o = a1;
 328         try {
 329             GetFlattenedArrayElementsWrapper(o);
 330         } catch(Throwable t) {
 331             exception = t;
 332         }
 333         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 334         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 335         exception = null;
 336         try {
 337             GetFlattenedArrayElementsWrapper(new String[16]);
 338         } catch(Throwable t) {
 339             exception = t;
 340         }
 341         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 342         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 343         exception = null;
 344         try {
 345             // Array of BigValue should not be flattened because BigValue is *big*
 346             GetFlattenedArrayElementsWrapper(new BigValue[16]);
 347         } catch(Throwable t) {
 348             exception = t;
 349         }
 350         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 351         Asserts.assertTrue(exception instanceof IllegalArgumentException , "Exception should be a IAE");
 352         exception = null;
 353         try {
 354             // Direct native access to flattened arrays is not allowed if elements contain oops
 355             GetFlattenedArrayElementsWrapper(new ValueWithOops[16]);
 356         } catch(Throwable t) {
 357             exception = t;
 358         }
 359         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 360         Asserts.assertTrue(exception instanceof IllegalArgumentException , "Exception should be a IAE");
 361         exception = null;
 362         long addr = 0;
 363         IntInt[] a2 = new IntInt[16];
 364         try {
 365             addr = GetFlattenedArrayElementsWrapper(a2);
 366         } catch(Throwable t) {
 367             exception = t;
 368         }
 369         Asserts.assertNull(exception, "No exception should have been thrown");
 370         if (exception == null) {
 371             ReleaseFlattenedArrayElementsWrapper(a2, addr, 0);
 372         }
 373     }
 374     
 375     void checkBehaviors() {
 376         System.out.println("Check 1");
 377         IntInt[] array = new IntInt[ARRAY_SIZE];
 378         int value = getIntFieldAtIndex(array, 1, "i0", "I");
 379         Asserts.assertEquals(value, 0, "Initial value must be zero");
 380         printArrayInformation(array);
 381         int i0_value = 42;
 382         int i1_value = -314;
 383         initializeIntIntArrayBuffer(array, i0_value, i1_value);
 384         System.gc();
 385         for (int i = 0; i < array.length; i++) {
 386             Asserts.assertEquals(array[i].i0, i0_value, "Bad value of i0 at index " + i);
 387             Asserts.assertEquals(array[i].i1, i1_value, "Bad value of i1 at index " + i);
 388         }
 389         System.out.println("Check 2");
 390         array = new IntInt[ARRAY_SIZE];
 391         i0_value = -194;
 392         i1_value = 91;
 393         initializeIntIntArrayFields(array, i0_value, i1_value);
 394         System.gc();
 395         for (int i = 0; i < array.length; i++) {
 396             Asserts.assertEquals(array[i].i0, i0_value, "Bad value of i0 at index " + i);
 397             Asserts.assertEquals(array[i].i1, i1_value, "Bad value of i1 at index " + i);
 398         }
 399         System.out.println("Check 3");
 400         array = new IntInt[ARRAY_SIZE];
 401         initializeIntIntArrayJava(array, i0_value, i1_value);
 402         System.gc();
 403         for (int i = 0; i < array.length; i++) {
 404             Asserts.assertEquals(array[i].i0, i0_value, "Bad value of i0 at index " + i);
 405             Asserts.assertEquals(array[i].i1, i1_value, "Bad value of i1 at index " + i);
 406         }
 407         System.out.println("Check 4");
 408         random = new Random(seed);
 409         array = new IntInt[ARRAY_SIZE];
 410         for (int i = 0; i < ARRAY_SIZE; i++) {
 411             array[i] = new IntInt(random.nextInt(), random.nextInt());
 412         }
 413         sortIntIntArray(array);
 414         System.gc();
 415         for (int i = 0; i < array.length - 1; i++) {
 416             Asserts.assertLessThanOrEqual(array[i].i0, array[i+1].i0, "Incorrect i0 fields ordering at index " + i);
 417             if (array[i].i0 == array[i+1].i0) {
 418                 Asserts.assertLessThanOrEqual(array[i].i1, array[i+1].i1, "Incorrect i1 fields ordering at index " + i);
 419             }
 420         }
 421         System.out.println("Check 5");
 422         random = new Random(seed);
 423         array = new IntInt[ARRAY_SIZE];
 424         for (int i = 0; i < ARRAY_SIZE; i++) {
 425             array[i] = new IntInt(random.nextInt(), random.nextInt());
 426         }
 427         Arrays.sort(array, new IntIntComparator());
 428         System.gc();
 429         for (int i = 0; i < array.length - 1; i++) {
 430             Asserts.assertLessThanOrEqual(array[i].i0, array[i+1].i0, "Incorrect i0 fields ordering at index " + i);
 431             if (array[i].i0 == array[i+1].i0) {
 432                 Asserts.assertLessThanOrEqual(array[i].i1, array[i+1].i1, "Incorrect i1 fields ordering at index " + i);
 433             }
 434         }
 435         System.out.println("Check 6");
 436         Container[] array2 = new Container[ARRAY_SIZE];
 437         double d  = 1.23456789;
 438         float f = -987.654321f;
 439         short s = -512;
 440         byte b = 127;
 441         Containee c = new Containee(f,s);
 442         Container c2 = new Container(d, c, b);
 443         initializeContainerArray(array2, d, f, s, b);
 444         System.gc();
 445         for (int i = 0; i < array2.length; i++) {
 446             Asserts.assertEquals(array2[i], c2, "Incorrect value at index " + i);
 447             Asserts.assertEquals(array2[i].d, d, "Incorrect d value at index " + i);
 448             Asserts.assertEquals(array2[i].c.f, f, "Incorrect f value at index " + i);
 449             Asserts.assertEquals(array2[i].c.s, s, "Incorrect s value at index " + i);
 450             Asserts.assertEquals(array2[i].b, b, "Incorrect b value at inde " +i);
 451         }
 452         System.out.println("Check 7");
 453         f = 19.2837465f;
 454         s = 231;
 455         updateContainerArray(array2, f, s);
 456         System.gc();
 457         for (int i = 0; i < array2.length; i++) {
 458             Asserts.assertEquals(array2[i].d, d, "Incorrect d value at index " + i);
 459             Asserts.assertEquals(array2[i].c.f, f, "Incorrect f value at index " + i);
 460             Asserts.assertEquals(array2[i].c.s, s, "Incorrect s value at index " + i);
 461             Asserts.assertEquals(array2[i].b, b, "Incorrect b value at inde " +i);
 462         }
 463         System.out.println("Check 8");
 464         long l0 = 52467923;
 465         long l1= -7854022;
 466         long l2 = 230947485;
 467         long l3 = -752497024;
 468         LongLongLongLong[] array3 = new LongLongLongLong[ARRAY_SIZE/8];
 469         initializeLongLongLongLongArray(array3, l0, l1, l2, l3);
 470         System.gc();
 471         for (int i = 0; i < array3.length; i++) {
 472             Asserts.assertEquals(array3[i].l0, l0, "Bad value of l0 at index " + i);
 473             Asserts.assertEquals(array3[i].l1, l1, "Bad value of l1 at index " + i);
 474             Asserts.assertEquals(array3[i].l2, l2, "Bad value of l2 at index " + i);
 475             Asserts.assertEquals(array3[i].l3, l3, "Bad value of l3 at index " + i);
 476         }
 477     }
 478 
 479     void initializeIntIntArrayJava(IntInt[] array, int i0, int i1) {
 480         IntInt ii = new IntInt(i0, i1);
 481         for (int i = 0; i < array.length; i++) {
 482             array[i] = ii;
 483         }
 484     }
 485 
 486     void initializeContainerArrayJava(Container[] array, double d, float f, short s, byte b) {
 487         Containee c = new Containee(f,s);
 488         Container c2 = new Container(d, c, b);
 489         for (int i = 0; i < array.length; i++) {
 490             array[i] = c2;
 491         }
 492     }
 493 
 494     void updateContainerArrayJava(Container[] array, float f, short s) {
 495         Containee c = new Containee(f, s);
 496         for (int i = 0; i < array.length; i++) {
 497             array[i] = array[i].setc(c);;
 498         }
 499     }
 500 
 501     void initializeLongLongLongLongArrayJava(LongLongLongLong[] array, long l0, long l1, long l2, long l3) {
 502         LongLongLongLong llll = new LongLongLongLong(l0, l1, l2, l3);
 503         for (int i = 0; i < array.length; i++) {
 504             array[i] = llll;
 505         }
 506     }
 507     
 508     void mesureInitializationTime(int array_size, int iterations) {
 509         System.out.println("\nInitialization time for IntInt[]:");
 510         long[] start = new long[iterations];
 511         long[] end = new long[iterations];
 512 
 513         
 514         System.out.println("\nJava:");
 515         // Warmup
 516         for (int i = 0; i < 10; i++) {
 517             IntInt[] array = new IntInt[array_size];
 518             initializeIntIntArrayJava(array, 42, -314);
 519         }
 520         // Measure
 521         for (int i = 0; i < iterations; i++) {
 522             IntInt[] array = new IntInt[array_size];
 523             start[i] = System.nanoTime();
 524             initializeIntIntArrayJava(array, 42, -314);
 525             end[i] = System.nanoTime();
 526         }
 527         // Results
 528         computeStatistics(start, end);
 529 
 530         System.out.println("\nNative(memcpy):");
 531         // Warmup
 532         for (int i = 0; i < 10; i++) {
 533             IntInt[] array = new IntInt[array_size];
 534             initializeIntIntArrayBuffer(array, 42, -314);
 535         }
 536         // Measure
 537         for (int i = 0; i < iterations; i++) {
 538             IntInt[] array = new IntInt[array_size];
 539             start[i] = System.nanoTime();
 540             initializeIntIntArrayBuffer(array, 42, -314);
 541             end[i] = System.nanoTime();
 542         }
 543         // Results
 544         computeStatistics(start, end);
 545         
 546         
 547         System.out.println("\nNative(fields):");
 548         // Warmup
 549         for (int i = 0; i < 10; i++) {
 550             IntInt[] array = new IntInt[array_size];
 551             initializeIntIntArrayFields(array, 42, -314);
 552         }
 553         // Measure
 554         for (int i = 0; i < iterations; i++) {
 555             IntInt[] array = new IntInt[array_size];
 556             start[i] = System.nanoTime();
 557             initializeIntIntArrayFields(array, 42, -314);
 558             end[i] = System.nanoTime();
 559         }
 560         // Results
 561         computeStatistics(start, end);
 562     }
 563 
 564     void mesureInitializationTime2(int array_size, int iterations) {
 565         System.out.println("\nInitialization time for Container[]:");
 566         long[] start = new long[iterations];
 567         long[] end = new long[iterations];
 568 
 569         double d = 0.369852147;
 570         float f = -321.654987f;
 571         short s = -3579;
 572         byte b = 42;
 573         
 574         System.out.println("\nJava:");
 575         // Warmup
 576         for (int i = 0; i < 10; i++) {
 577             Container[] array = new Container[array_size];
 578             initializeContainerArrayJava(array, d, f, s, b);
 579         }
 580         // Measure
 581         for (int i = 0; i < iterations; i++) {
 582             Container[] array = new Container[array_size];
 583             start[i] = System.nanoTime();
 584             initializeContainerArrayJava(array, d, f, s, b);
 585             end[i] = System.nanoTime();
 586         }
 587         // Results
 588         computeStatistics(start, end);
 589 
 590         System.out.println("\nNative:");
 591         // Warmup
 592         for (int i = 0; i < 10; i++) {
 593             Container[] array = new Container[array_size];
 594             initializeContainerArray(array, d, f, s, b);
 595         }
 596         // Measure
 597         for (int i = 0; i < iterations; i++) {
 598             Container[] array = new Container[array_size];
 599             start[i] = System.nanoTime();
 600             initializeContainerArray(array, d, f, s, b);
 601             end[i] = System.nanoTime();
 602         }
 603         // Results
 604         computeStatistics(start, end);
 605     }
 606 
 607     void mesureUpdateTime2(int array_size, int iterations) {
 608         System.out.println("\nUpdating Container[]:");
 609         long[] start = new long[iterations];
 610         long[] end = new long[iterations];
 611 
 612         double d = 0.369852147;
 613         float f = -321.654987f;
 614         short s = -3579;
 615         byte b = 42;
 616 
 617         Containee c = new Containee(f,s);
 618         Container c2 = new Container(d, c, b);
 619         
 620         System.out.println("\nJava:");
 621         // Warmup
 622         for (int i = 0; i < 10; i++) {
 623             Container[] array = new Container[array_size];
 624             for (int j = 0; j < array.length; j++) {
 625                 array[j] = c2;
 626             }
 627             updateContainerArrayJava(array, f, s);
 628         }
 629         // Measure
 630         for (int i = 0; i < iterations; i++) {
 631             Container[] array = new Container[array_size];
 632             for (int j = 0; j < array.length; j++) {
 633                 array[i] = c2;
 634             }
 635             start[i] = System.nanoTime();
 636             updateContainerArrayJava(array, f, s);
 637             end[i] = System.nanoTime();
 638         }
 639         // Results
 640         computeStatistics(start, end);
 641 
 642         System.out.println("\nNative:");
 643         // Warmup
 644         for (int i = 0; i < 10; i++) {
 645             Container[] array = new Container[array_size];
 646             for (int j = 0; j < array.length; j++) {
 647                 array[i] = c2;
 648             }
 649             updateContainerArray(array, f, s);
 650         }
 651         // Measure
 652         for (int i = 0; i < iterations; i++) {
 653             Container[] array = new Container[array_size];
 654             for (int j = 0; j < array.length; j++) {
 655                 array[i] = c2;
 656             }
 657             start[i] = System.nanoTime();
 658             updateContainerArray(array, f, s);
 659             end[i] = System.nanoTime();
 660         }
 661         // Results
 662         computeStatistics(start, end);
 663     }
 664     
 665     void mesureSortingTime(int array_size, int iterations) {
 666         System.out.println("\nSorting time:");
 667         long[] start = new long[iterations];
 668         long[] end = new long[iterations];
 669 
 670         random = new Random(seed);
 671         System.out.println("\nJava:");
 672         IntIntComparator comparator = new IntIntComparator();
 673         // Warmup
 674         for (int i = 0; i < 10; i++) {
 675             IntInt[] array = new IntInt[array_size];
 676             array = new IntInt[array_size];
 677             for (int j = 0; j < array_size; j++) {
 678                 array[j] = new IntInt(random.nextInt(), random.nextInt());
 679             }
 680             Arrays.sort(array, comparator);
 681         }
 682         // Measure
 683         for (int i = 0; i < iterations; i++) {
 684             IntInt[] array = new IntInt[array_size];
 685             for (int j = 0; j < array_size; j++) {
 686                 array[j] = new IntInt(random.nextInt(), random.nextInt());
 687             }
 688             start[i] = System.nanoTime();
 689             Arrays.sort(array, comparator);
 690             end[i] = System.nanoTime();
 691         }
 692         // Results
 693         computeStatistics(start, end);
 694 
 695         random = new Random(seed);
 696         System.out.println("\nNative:");
 697         // Warmup
 698         for (int i = 0; i < 10; i++) {
 699             IntInt[] array = new IntInt[array_size];
 700             array = new IntInt[array_size];
 701             for (int j = 0; j < array_size; j++) {
 702                 array[j] = new IntInt(random.nextInt(), random.nextInt());
 703             }
 704             sortIntIntArray(array);
 705         }
 706         // Measure
 707         for (int i = 0; i < iterations; i++) {
 708             IntInt[] array = new IntInt[array_size];
 709             for (int j = 0; j < array_size; j++) {
 710                 array[j] = new IntInt(random.nextInt(), random.nextInt());
 711             }
 712             start[i] = System.nanoTime();
 713             sortIntIntArray(array);
 714             end[i] = System.nanoTime();
 715         }
 716         // Results
 717         computeStatistics(start, end);
 718     }
 719 
 720 
 721     void mesureInitializationTime3(int array_size, int iterations) {
 722         System.out.println("\nInitialization time for LongLongLongLong[]:");
 723         long[] start = new long[iterations];
 724         long[] end = new long[iterations];
 725 
 726         long l0 = 123456;
 727         long l1 = -987654;
 728         long l2 = 192837;
 729         long l3 = -56473829;
 730         
 731         System.out.println("\nJava:");
 732         // Warmup
 733         for (int i = 0; i < 10; i++) {
 734             LongLongLongLong[] array = new LongLongLongLong[array_size];
 735             initializeLongLongLongLongArrayJava(array, l0, l1, l2, l3);
 736         }
 737         // Measure
 738         for (int i = 0; i < iterations; i++) {
 739             LongLongLongLong[] array = new LongLongLongLong[array_size];
 740             start[i] = System.nanoTime();
 741             initializeLongLongLongLongArrayJava(array, l0, l1, l2, l3);
 742             end[i] = System.nanoTime();
 743         }
 744         // Results
 745         computeStatistics(start, end);
 746 
 747         System.out.println("\nNative:");
 748         // Warmup
 749         for (int i = 0; i < 10; i++) {
 750             LongLongLongLong[] array = new LongLongLongLong[array_size];
 751             initializeLongLongLongLongArray(array, l0, l1, l2, l3);
 752         }
 753         // Measure
 754         for (int i = 0; i < iterations; i++) {
 755             LongLongLongLong[] array = new LongLongLongLong[array_size];
 756             start[i] = System.nanoTime();
 757             initializeLongLongLongLongArray(array, l0, l1, l2, l3);
 758             end[i] = System.nanoTime();
 759         }
 760         // Results
 761         computeStatistics(start, end);
 762     }
 763     
 764     void computeStatistics(long[] start, long[] end) {
 765         int iterations = start.length;
 766         long[] duration = new long[iterations];
 767         long sum = 0;
 768         long min = end[0] - start[0];
 769         long max = min;
 770         double var = 0.0;
 771         for (int i = 0 ; i < iterations; i++) {
 772             duration[i] = end[i] - start[i];
 773             if (duration[i] < min) min = duration[i];
 774             if (duration[i] > max) max = duration[i];
 775             sum += duration[i];
 776             double d = (double) duration[i];
 777             var += Math.pow(d, 2);
 778         }
 779         double avg = (sum/iterations) / 1000;
 780         double std = (Math.sqrt(var/iterations - Math.pow(sum/iterations, 2))) / 1000;
 781         System.out.println(String.format("Avg: %8.2f us", avg));
 782         System.out.println(String.format("Std: %8.2f us", std));
 783         System.out.println(String.format("Min: %8d us", (min/1000)));
 784         System.out.println(String.format("Max: %8d us", (max/1000)));
 785     }
 786 
 787     native int GetFlattenedArrayElementSizeWrapper(Object array);
 788     native Class GetFlattenedArrayElementClassWrapper(Object array);
 789     native long GetFlattenedArrayElementsWrapper(Object array);
 790     native void ReleaseFlattenedArrayElementsWrapper(Object array, long addr,int mode);
 791     native int GetFieldOffsetInFlattenedLayoutWrapper(Class klass, String name, String signature, boolean flattened);
 792     
 793     native int getIntFieldAtIndex(Object[] array, int index, String fieldName, String FieldSignature);
 794     native void printArrayInformation(Object[] array);
 795 
 796     native void initializeIntIntArrayBuffer(Object[] array, int i0, int i1);
 797     native void initializeIntIntArrayFields(Object[] array, int i0, int i1);
 798     native void sortIntIntArray(Object[] array);
 799 
 800     native void initializeContainerArray(Object[] array, double d, float f, short s, byte b);
 801     native void updateContainerArray(Object[] array, float f, short s);
 802 
 803     native void initializeLongLongLongLongArray(Object[] array, long l0, long l1, long l2, long l3);
 804 }