1 /*
   2  * Copyright (c) 2016, 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 /*
  26  * @test
  27  * @bug 8150465
  28  * @summary Unsafe methods to produce uninitialized arrays
  29  * @modules java.base/jdk.internal.misc
  30  * @run main/othervm -ea -Diters=200   -Xint                   AllocateUninitializedArray
  31  * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=1 AllocateUninitializedArray
  32  * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=4 AllocateUninitializedArray
  33  */
  34 import java.lang.reflect.Field;
  35 import java.lang.reflect.Array;
  36 import java.util.concurrent.Callable;
  37 
  38 public class AllocateUninitializedArray {
  39     static final int ITERS = Integer.getInteger("iters", 1);
  40     static final jdk.internal.misc.Unsafe UNSAFE;
  41 
  42     static {
  43         try {
  44             Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
  45             f.setAccessible(true);
  46             UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
  47         } catch (Exception e) {
  48             throw new RuntimeException("Unable to get Unsafe instance.", e);
  49         }
  50     }
  51 
  52     public static void main(String... args) throws Exception {
  53         testIAE(AllConstants::testObject);
  54         testIAE(LengthIsConstant::testObject);
  55         testIAE(ClassIsConstant::testObject);
  56         testIAE(NothingIsConstant::testObject);
  57 
  58         testIAE(AllConstants::testArray);
  59         testIAE(LengthIsConstant::testArray);
  60         testIAE(ClassIsConstant::testArray);
  61         testIAE(NothingIsConstant::testArray);
  62 
  63         testIAE(AllConstants::testNull);
  64         testIAE(LengthIsConstant::testNull);
  65         testIAE(ClassIsConstant::testNull);
  66         testIAE(NothingIsConstant::testNull);
  67 
  68         testOK(boolean[].class, 10, AllConstants::testBoolean);
  69         testOK(byte[].class,    10, AllConstants::testByte);
  70         testOK(short[].class,   10, AllConstants::testShort);
  71         testOK(char[].class,    10, AllConstants::testChar);
  72         testOK(int[].class,     10, AllConstants::testInt);
  73         testOK(float[].class,   10, AllConstants::testFloat);
  74         testOK(long[].class,    10, AllConstants::testLong);
  75         testOK(double[].class,  10, AllConstants::testDouble);
  76 
  77         testOK(boolean[].class, 10, LengthIsConstant::testBoolean);
  78         testOK(byte[].class,    10, LengthIsConstant::testByte);
  79         testOK(short[].class,   10, LengthIsConstant::testShort);
  80         testOK(char[].class,    10, LengthIsConstant::testChar);
  81         testOK(int[].class,     10, LengthIsConstant::testInt);
  82         testOK(float[].class,   10, LengthIsConstant::testFloat);
  83         testOK(long[].class,    10, LengthIsConstant::testLong);
  84         testOK(double[].class,  10, LengthIsConstant::testDouble);
  85 
  86         testOK(boolean[].class, 10, ClassIsConstant::testBoolean);
  87         testOK(byte[].class,    10, ClassIsConstant::testByte);
  88         testOK(short[].class,   10, ClassIsConstant::testShort);
  89         testOK(char[].class,    10, ClassIsConstant::testChar);
  90         testOK(int[].class,     10, ClassIsConstant::testInt);
  91         testOK(float[].class,   10, ClassIsConstant::testFloat);
  92         testOK(long[].class,    10, ClassIsConstant::testLong);
  93         testOK(double[].class,  10, ClassIsConstant::testDouble);
  94 
  95         testOK(boolean[].class, 10, NothingIsConstant::testBoolean);
  96         testOK(byte[].class,    10, NothingIsConstant::testByte);
  97         testOK(short[].class,   10, NothingIsConstant::testShort);
  98         testOK(char[].class,    10, NothingIsConstant::testChar);
  99         testOK(int[].class,     10, NothingIsConstant::testInt);
 100         testOK(float[].class,   10, NothingIsConstant::testFloat);
 101         testOK(long[].class,    10, NothingIsConstant::testLong);
 102         testOK(double[].class,  10, NothingIsConstant::testDouble);
 103     }
 104 
 105     public static void testOK(Class<?> expectClass, int expectLen, Callable<Object> test) throws Exception {
 106         for (int c = 0; c < ITERS; c++) {
 107             Object res = test.call();
 108             Class<?> actualClass = res.getClass();
 109             if (!actualClass.equals(expectClass)) {
 110                 throw new IllegalStateException("Wrong class: expected = " + expectClass + ", but got " + actualClass);
 111             }
 112             int actualLen = Array.getLength(res);
 113             if (actualLen != expectLen) {
 114                 throw new IllegalStateException("Wrong length: expected = " + expectLen + ", but got " + actualLen);
 115             }
 116         }
 117     }
 118 
 119     static volatile Object sink;
 120 
 121     public static void testIAE(Callable<Object> test) throws Exception {
 122         for (int c = 0; c < ITERS; c++) {
 123             try {
 124                sink = test.call();
 125                throw new IllegalStateException("Expected IAE");
 126             } catch (IllegalArgumentException iae) {
 127                // expected
 128             }
 129         }
 130     }
 131 
 132     static volatile int sampleLenNeg  = -1;
 133     static volatile int sampleLenZero = 0;
 134     static volatile int sampleLen     = 10;
 135 
 136 
 137     static volatile Class<?> classBoolean = boolean.class;
 138     static volatile Class<?> classByte    = byte.class;
 139     static volatile Class<?> classShort   = short.class;
 140     static volatile Class<?> classChar    = char.class;
 141     static volatile Class<?> classInt     = int.class;
 142     static volatile Class<?> classFloat   = float.class;
 143     static volatile Class<?> classLong    = long.class;
 144     static volatile Class<?> classDouble  = double.class;
 145     static volatile Class<?> classObject  = Object.class;
 146     static volatile Class<?> classArray   = Object[].class;
 147     static volatile Class<?> classNull    = null;
 148 
 149     static class AllConstants {
 150         static Object testBoolean() { return UNSAFE.allocateUninitializedArray(boolean.class,  10); }
 151         static Object testByte()    { return UNSAFE.allocateUninitializedArray(byte.class,     10); }
 152         static Object testShort()   { return UNSAFE.allocateUninitializedArray(short.class,    10); }
 153         static Object testChar()    { return UNSAFE.allocateUninitializedArray(char.class,     10); }
 154         static Object testInt()     { return UNSAFE.allocateUninitializedArray(int.class,      10); }
 155         static Object testFloat()   { return UNSAFE.allocateUninitializedArray(float.class,    10); }
 156         static Object testLong()    { return UNSAFE.allocateUninitializedArray(long.class,     10); }
 157         static Object testDouble()  { return UNSAFE.allocateUninitializedArray(double.class,   10); }
 158         static Object testObject()  { return UNSAFE.allocateUninitializedArray(Object.class,   10); }
 159         static Object testArray()   { return UNSAFE.allocateUninitializedArray(Object[].class, 10); }
 160         static Object testNull()    { return UNSAFE.allocateUninitializedArray(null,           10); }
 161         static Object testZero()    { return UNSAFE.allocateUninitializedArray(int.class,      0);  }
 162         static Object testNeg()     { return UNSAFE.allocateUninitializedArray(int.class,      -1); }
 163     }
 164 
 165     static class ClassIsConstant {
 166         static Object testBoolean() { return UNSAFE.allocateUninitializedArray(boolean.class,  sampleLen); }
 167         static Object testByte()    { return UNSAFE.allocateUninitializedArray(byte.class,     sampleLen); }
 168         static Object testShort()   { return UNSAFE.allocateUninitializedArray(short.class,    sampleLen); }
 169         static Object testChar()    { return UNSAFE.allocateUninitializedArray(char.class,     sampleLen); }
 170         static Object testInt()     { return UNSAFE.allocateUninitializedArray(int.class,      sampleLen); }
 171         static Object testFloat()   { return UNSAFE.allocateUninitializedArray(float.class,    sampleLen); }
 172         static Object testLong()    { return UNSAFE.allocateUninitializedArray(long.class,     sampleLen); }
 173         static Object testDouble()  { return UNSAFE.allocateUninitializedArray(double.class,   sampleLen); }
 174         static Object testObject()  { return UNSAFE.allocateUninitializedArray(Object.class,   sampleLen); }
 175         static Object testArray()   { return UNSAFE.allocateUninitializedArray(Object[].class, sampleLen); }
 176         static Object testNull()    { return UNSAFE.allocateUninitializedArray(null,           sampleLen); }
 177         static Object testZero()    { return UNSAFE.allocateUninitializedArray(int.class,      sampleLenZero); }
 178         static Object testNeg()     { return UNSAFE.allocateUninitializedArray(int.class,      sampleLenNeg); }
 179     }
 180 
 181     static class LengthIsConstant {
 182         static Object testBoolean() { return UNSAFE.allocateUninitializedArray(classBoolean, 10); }
 183         static Object testByte()    { return UNSAFE.allocateUninitializedArray(classByte,    10); }
 184         static Object testShort()   { return UNSAFE.allocateUninitializedArray(classShort,   10); }
 185         static Object testChar()    { return UNSAFE.allocateUninitializedArray(classChar,    10); }
 186         static Object testInt()     { return UNSAFE.allocateUninitializedArray(classInt,     10); }
 187         static Object testFloat()   { return UNSAFE.allocateUninitializedArray(classFloat,   10); }
 188         static Object testLong()    { return UNSAFE.allocateUninitializedArray(classLong,    10); }
 189         static Object testDouble()  { return UNSAFE.allocateUninitializedArray(classDouble,  10); }
 190         static Object testObject()  { return UNSAFE.allocateUninitializedArray(classObject,  10); }
 191         static Object testArray()   { return UNSAFE.allocateUninitializedArray(classArray,   10); }
 192         static Object testNull()    { return UNSAFE.allocateUninitializedArray(classNull,    10); }
 193         static Object testZero()    { return UNSAFE.allocateUninitializedArray(classInt,     0);  }
 194         static Object testNeg()     { return UNSAFE.allocateUninitializedArray(classInt,     -1); }
 195     }
 196 
 197     static class NothingIsConstant {
 198         static Object testBoolean() { return UNSAFE.allocateUninitializedArray(classBoolean, sampleLen); }
 199         static Object testByte()    { return UNSAFE.allocateUninitializedArray(classByte,    sampleLen); }
 200         static Object testShort()   { return UNSAFE.allocateUninitializedArray(classShort,   sampleLen); }
 201         static Object testChar()    { return UNSAFE.allocateUninitializedArray(classChar,    sampleLen); }
 202         static Object testInt()     { return UNSAFE.allocateUninitializedArray(classInt,     sampleLen); }
 203         static Object testFloat()   { return UNSAFE.allocateUninitializedArray(classFloat,   sampleLen); }
 204         static Object testLong()    { return UNSAFE.allocateUninitializedArray(classLong,    sampleLen); }
 205         static Object testDouble()  { return UNSAFE.allocateUninitializedArray(classDouble,  sampleLen); }
 206         static Object testObject()  { return UNSAFE.allocateUninitializedArray(classObject,  sampleLen); }
 207         static Object testArray()   { return UNSAFE.allocateUninitializedArray(classArray,   sampleLen); }
 208         static Object testNull()    { return UNSAFE.allocateUninitializedArray(classNull,    sampleLen); }
 209         static Object testZero()    { return UNSAFE.allocateUninitializedArray(classInt,     sampleLenZero); }
 210         static Object testNeg()     { return UNSAFE.allocateUninitializedArray(classInt,     sampleLenNeg); }
 211     }
 212 }
 213