1 /* 2 * Copyright (c) 2013, 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 import java.io.BufferedReader; 25 import java.io.InputStreamReader; 26 import java.lang.Class; 27 import java.lang.String; 28 import java.lang.System; 29 import java.lang.management.ManagementFactory; 30 import java.lang.management.RuntimeMXBean; 31 import java.util.ArrayList; 32 import java.util.List; 33 import java.util.concurrent.CyclicBarrier; 34 import java.util.regex.Matcher; 35 import java.util.regex.Pattern; 36 import java.lang.reflect.Field; 37 import java.lang.reflect.Modifier; 38 import jdk.internal.misc.Unsafe; 39 import jdk.internal.vm.annotation.Contended; 40 41 /* 42 * @test 43 * @bug 8003985 44 * @summary Support Contended Annotation - JEP 142 45 * @modules java.base/jdk.internal.misc 46 * @modules java.base/jdk.internal.vm.annotation 47 * @run main/othervm -XX:-RestrictContended Basic 48 */ 49 public class Basic { 50 51 private static final Unsafe U = Unsafe.getUnsafe(); 52 private static int ADDRESS_SIZE; 53 private static int HEADER_SIZE; 54 55 static { 56 // When running with CompressedOops on 64-bit platform, the address size 57 // reported by Unsafe is still 8, while the real reference fields are 4 bytes long. 58 // Try to guess the reference field size with this naive trick. 59 try { 60 long off1 = U.objectFieldOffset(CompressedOopsClass.class.getField("obj1")); 61 long off2 = U.objectFieldOffset(CompressedOopsClass.class.getField("obj2")); 62 ADDRESS_SIZE = (int) Math.abs(off2 - off1); 63 HEADER_SIZE = (int) Math.min(off1, off2); 64 } catch (NoSuchFieldException e) { 65 ADDRESS_SIZE = -1; 66 } 67 } 68 69 static class CompressedOopsClass { 70 public Object obj1; 71 public Object obj2; 72 } 73 74 public static boolean arePaddedPairwise(Class klass, String field1, String field2) throws Exception { 75 Field f1 = klass.getDeclaredField(field1); 76 Field f2 = klass.getDeclaredField(field2); 77 78 if (isStatic(f1) != isStatic(f2)) { 79 return true; // these guys are in naturally disjoint locations 80 } 81 82 int diff = offset(f1) - offset(f2); 83 if (diff < 0) { 84 // f1 is first 85 return (offset(f2) - (offset(f1) + getSize(f1))) > 64; 86 } else { 87 // f2 is first 88 return (offset(f1) - (offset(f2) + getSize(f2))) > 64; 89 } 90 } 91 92 public static boolean isPadded(Class klass, String field1) throws Exception { 93 Field f1 = klass.getDeclaredField(field1); 94 95 if (isStatic(f1)) { 96 return offset(f1) > 128 + 64; 97 } 98 99 return offset(f1) > 64; 100 } 101 102 public static boolean sameLayout(Class klass1, Class klass2) throws Exception { 103 for (Field f1 : klass1.getDeclaredFields()) { 104 Field f2 = klass2.getDeclaredField(f1.getName()); 105 if (offset(f1) != offset(f2)) { 106 return false; 107 } 108 } 109 110 for (Field f2 : klass1.getDeclaredFields()) { 111 Field f1 = klass2.getDeclaredField(f2.getName()); 112 if (offset(f1) != offset(f2)) { 113 return false; 114 } 115 } 116 117 return true; 118 } 119 120 public static boolean isStatic(Field field) { 121 return Modifier.isStatic(field.getModifiers()); 122 } 123 124 public static int offset(Field field) { 125 if (isStatic(field)) { 126 return (int) U.staticFieldOffset(field); 127 } else { 128 return (int) U.objectFieldOffset(field); 129 } 130 } 131 132 public static int getSize(Field field) { 133 Class type = field.getType(); 134 if (type == byte.class) { return 1; } 135 if (type == boolean.class) { return 1; } 136 if (type == short.class) { return 2; } 137 if (type == char.class) { return 2; } 138 if (type == int.class) { return 4; } 139 if (type == float.class) { return 4; } 140 if (type == long.class) { return 8; } 141 if (type == double.class) { return 8; } 142 return ADDRESS_SIZE; 143 } 144 145 public static void main(String[] args) throws Exception { 146 boolean endResult = true; 147 148 // --------------- INSTANCE FIELDS --------------------- 149 150 if (arePaddedPairwise(Test1.class, "int1", "int2") || 151 isPadded(Test1.class, "int1") || 152 isPadded(Test1.class, "int2")) { 153 System.err.println("Test1 failed"); 154 endResult &= false; 155 } 156 157 if (!arePaddedPairwise(Test2.class, "int1", "int2") || 158 !isPadded(Test2.class, "int1") || 159 isPadded(Test2.class, "int2")) { 160 System.err.println("Test2 failed"); 161 endResult &= false; 162 } 163 164 if (!arePaddedPairwise(Test3.class, "int1", "int2") || 165 !isPadded(Test3.class, "int1") || 166 !isPadded(Test3.class, "int2")) { 167 System.err.println("Test3 failed"); 168 endResult &= false; 169 } 170 171 if (arePaddedPairwise(Test4.class, "int1", "int2") || 172 !isPadded(Test4.class, "int1") || 173 !isPadded(Test4.class, "int2")) { 174 System.err.println("Test4 failed"); 175 endResult &= false; 176 } 177 178 if (!arePaddedPairwise(Test5.class, "int1", "int2") || 179 !isPadded(Test5.class, "int1") || 180 !isPadded(Test5.class, "int2")) { 181 System.err.println("Test5 failed"); 182 endResult &= false; 183 } 184 185 if (!arePaddedPairwise(Test6.class, "int1", "int2") || 186 !isPadded(Test6.class, "int1") || 187 !isPadded(Test6.class, "int2")) { 188 System.err.println("Test6 failed"); 189 endResult &= false; 190 } 191 192 if (arePaddedPairwise(Test7.class, "int1", "int2") || 193 !isPadded(Test7.class, "int1") || 194 !isPadded(Test7.class, "int2")) { 195 System.err.println("Test7 failed"); 196 endResult &= false; 197 } 198 199 if (!arePaddedPairwise(Test8.class, "int1", "int2") || 200 !isPadded(Test8.class, "int1") || 201 !isPadded(Test8.class, "int2")) { 202 System.err.println("Test8 failed"); 203 endResult &= false; 204 } 205 206 if (!arePaddedPairwise(Test9.class, "int1", "int2") || 207 !isPadded(Test9.class, "int1") || 208 !isPadded(Test9.class, "int2")) { 209 System.err.println("Test9 failed"); 210 endResult &= false; 211 } 212 213 if (!sameLayout(Test4.class, Test7.class)) { 214 System.err.println("Test4 and Test7 have different layouts"); 215 endResult &= false; 216 } 217 218 if (!sameLayout(Test5.class, Test6.class)) { 219 System.err.println("Test5 and Test6 have different layouts"); 220 endResult &= false; 221 } 222 223 if (!sameLayout(Test8.class, Test9.class)) { 224 System.err.println("Test8 and Test9 have different layouts"); 225 endResult &= false; 226 } 227 228 System.out.println(endResult ? "Test PASSES" : "Test FAILS"); 229 if (!endResult) { 230 throw new Error("Test failed"); 231 } 232 } 233 234 // ----------------------------------- INSTANCE FIELDS ----------------------------------------- 235 236 // naturally packed 237 public static class Test1 { 238 private int int1; 239 private int int2; 240 } 241 242 // int1 is padded 243 public static class Test2 { 244 @Contended private int int1; 245 private int int2; 246 } 247 248 // both fields are padded 249 public static class Test3 { 250 @Contended private int int1; 251 @Contended private int int2; 252 } 253 254 // fields are padded in the singular group 255 public static class Test4 { 256 @Contended("sameGroup") private int int1; 257 @Contended("sameGroup") private int int2; 258 } 259 260 // fields are padded in disjoint groups 261 public static class Test5 { 262 @Contended("diffGroup1") private int int1; 263 @Contended("diffGroup2") private int int2; 264 } 265 266 // fields are padded in disjoint groups 267 public static class Test6 { 268 @Contended private int int1; 269 @Contended("diffGroup2") private int int2; 270 } 271 272 // fields are padded in the singular group 273 @Contended 274 public static class Test7 { 275 private int int1; 276 private int int2; 277 } 278 279 // all fields are padded as the group, and one field is padded specifically 280 @Contended 281 public static class Test8 { 282 @Contended private int int1; 283 private int int2; 284 } 285 286 // all fields are padded as the group, and one field is padded specifically 287 @Contended 288 public static class Test9 { 289 @Contended("group") private int int1; 290 private int int2; 291 } 292 293 } 294