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