1 /* 2 * Copyright (c) 2020, 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 8237767 27 * @summary Verify behaviour of field layout algorithm 28 * @library /test/lib 29 * @modules java.base/jdk.internal.misc 30 * java.management 31 * @run main/othervm FieldDensityTest 32 */ 33 34 /* 35 * @test 36 * @requires vm.bits == "64" 37 * @library /test/lib 38 * @modules java.base/jdk.internal.misc 39 * java.management 40 * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers FieldDensityTest 41 */ 42 43 import java.lang.reflect.Field; 44 import java.util.Arrays; 45 import java.util.Comparator; 46 import jdk.internal.misc.Unsafe; 47 48 import jdk.test.lib.Asserts; 49 50 public class FieldDensityTest { 51 52 static int OOP_SIZE_IN_BYTES = 0; 53 54 static { 55 if (System.getProperty("sun.arch.data.model").equals("64")) { 56 if (System.getProperty("java.vm.compressedOopsMode") == null) { 57 OOP_SIZE_IN_BYTES = 8; 58 } else { 59 OOP_SIZE_IN_BYTES = 4; 60 } 61 } else { 62 OOP_SIZE_IN_BYTES = 4; 63 } 64 } 65 66 static class FieldInfo { 67 public Field field; 68 public long offset; 69 70 FieldInfo(Field field, long offset) { 71 this.field = field; 72 this.offset = offset; 73 } 74 75 static void checkFieldsContiguity(FieldInfo[] fieldInfo) { 76 Arrays.sort(fieldInfo, new SortByOffset()); 77 for (int i = 0 ; i < fieldInfo.length - 2; i++) { 78 int size = sizeInBytesFromType(fieldInfo[i].field.getType()); 79 Asserts.assertEquals((int)(fieldInfo[i].offset + size), (int)fieldInfo[i+1].offset, 80 "Empty slot between fields, should not happen"); 81 } 82 } 83 } 84 85 static int sizeInBytesFromType(Class type) { 86 if (!type.isPrimitive()) { 87 return OOP_SIZE_IN_BYTES; 88 } 89 switch(type.getTypeName()) { 90 case "boolean": 91 case "byte": return 1; 92 case "char": 93 case "short": return 2; 94 case "int": 95 case "float": return 4; 96 case "long": 97 case "double": return 8; 98 default: 99 throw new RuntimeException("Unrecognized signature"); 100 } 101 } 102 103 static class SortByOffset implements Comparator<FieldInfo> { 104 public int compare(FieldInfo a, FieldInfo b) 105 { 106 return (int)(a.offset - b.offset); 107 } 108 } 109 110 static class E { 111 public byte b0; 112 } 113 114 static class F extends E { 115 public byte b1; 116 } 117 118 static class G extends F { 119 public byte b2; 120 } 121 122 static class H extends G { 123 public byte b3; 124 } 125 126 public static class A { 127 public int i; 128 public byte b; 129 public long l; 130 public Object o; 131 } 132 133 public static class B extends A { 134 public byte b0, b1, b2; 135 } 136 137 static void testFieldsContiguity(Class c) { 138 Unsafe unsafe = Unsafe.getUnsafe(); 139 Field[] fields = c.getFields(); 140 FieldInfo[] fieldsInfo = new FieldInfo[fields.length]; 141 int i = 0; 142 for (Field f : fields) { 143 long offset = unsafe.objectFieldOffset(f); 144 fieldsInfo[i] = new FieldInfo(f, offset); 145 i++; 146 } 147 FieldInfo.checkFieldsContiguity(fieldsInfo); 148 } 149 150 public static void main(String[] args) { 151 H h = new H(); 152 testFieldsContiguity(h.getClass()); 153 B b = new B(); 154 testFieldsContiguity(b.getClass()); 155 } 156 }