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 }
--- EOF ---