Skip to content

Instantly share code, notes, and snippets.

@rednaxelafx
Created June 21, 2011 13:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rednaxelafx/1037866 to your computer and use it in GitHub Desktop.
Save rednaxelafx/1037866 to your computer and use it in GitHub Desktop.
HotSpot's FieldsAllocationStyle=2 doesn't work as expected?
class A {
Object a1;
int a2;
}
class B extends A {
Object b1;
int b2;
float b3;
}
class C extends B {
Object c1;
float c2;
int c3;
}
class D extends C {
Object d1;
int d2;
}
$ export JAVA_OPTS='-XX:FieldsAllocationStyle=2'
$ groovysh
Groovy Shell (1.7.6, JVM: 1.6.0_26)
Type 'help' or '\h' for help.
-------------------------------------------------------------------------------
groovy:000> ObjectLayouts.printInstanceFieldOffsets(D)
Instance field offsets for class D:
+12: [A] a1 : class java.lang.Object
+8: [A] a2 : int
+24: [B] b1 : class java.lang.Object
+16: [B] b2 : int
+20: [B] b3 : float
+36: [C] c1 : class java.lang.Object
+28: [C] c2 : float
+32: [C] c3 : int
+44: [D] d1 : class java.lang.Object
+40: [D] d2 : int
===> null
groovy:000> import java.lang.management.ManagementFactory
===> [import java.lang.management.ManagementFactory]
groovy:000> import com.sun.management.HotSpotDiagnosticMXBean
===> [import java.lang.management.ManagementFactory, import com.sun.management.HotSpotDiagnosticMXBean]
groovy:000> HOTSPOT_BEAN_NAME = 'com.sun.management:type=HotSpotDiagnostic'
===> com.sun.management:type=HotSpotDiagnostic
groovy:000> server = ManagementFactory.platformMBeanServer
===> com.sun.jmx.mbeanserver.JmxMBeanServer@8ddb93
groovy:000> bean = ManagementFactory.newPlatformMXBeanProxy(server, HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean)
===> MXBeanProxy(com.sun.jmx.mbeanserver.JmxMBeanServer@8ddb93[com.sun.management:type=HotSpotDiagnostic])
groovy:000> bean.getVMOption('FieldsAllocationStyle')
===> VM option: FieldsAllocationStyle value: 2 origin: VM_CREATION (read-write)
groovy:000>
$ export JAVA_OPTS='-XX:FieldsAllocationStyle=2'
$ groovysh
Groovy Shell (1.7.6, JVM: 1.6.0_26)
Type 'help' or '\h' for help.
-------------------------------------------------------------------------------
groovy:000> ObjectLayouts.printInstanceFieldOffsets(D)
Instance field offsets for class D:
+12: [A] a1 : class java.lang.Object
+8: [A] a2 : int
+24: [B] b1 : class java.lang.Object
+16: [B] b2 : int
+20: [B] b3 : float
+36: [C] c1 : class java.lang.Object
+28: [C] c2 : float
+32: [C] c3 : int
+44: [D] d1 : class java.lang.Object
+40: [D] d2 : int
===> null
groovy:000> import java.lang.management.ManagementFactory
===> [import java.lang.management.ManagementFactory]
groovy:000> import com.sun.management.HotSpotDiagnosticMXBean
===> [import java.lang.management.ManagementFactory, import com.sun.management.HotSpotDiagnosticMXBean]
groovy:000> HOTSPOT_BEAN_NAME = 'com.sun.management:type=HotSpotDiagnostic'
===> com.sun.management:type=HotSpotDiagnostic
groovy:000> server = ManagementFactory.platformMBeanServer
===> com.sun.jmx.mbeanserver.JmxMBeanServer@8ddb93
groovy:000> bean = ManagementFactory.newPlatformMXBeanProxy(server, HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean)
===> MXBeanProxy(com.sun.jmx.mbeanserver.JmxMBeanServer@8ddb93[com.sun.management:type=HotSpotDiagnostic])
groovy:000> bean.getVMOption('FieldsAllocationStyle')
===> VM option: FieldsAllocationStyle value: 2 origin: VM_CREATION (read-write)
groovy:000>
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Fields {
public static boolean isStatic(Field f) {
return Modifier.isStatic(f.getModifiers());
}
}

I thought FieldsAllocationStyle=2 was supposed to alternate between FieldsAllocationStyle=0 and 1 in an inheritance chain. But that doesn't seem to be the case in this example.

I was expecting the output to be something like this:

Instance field offsets for class D:
  +12:  [A] a1 : class java.lang.Object
  +8:   [A] a2 : int
  +16:  [B] b1 : class java.lang.Object
  +20:  [B] b2 : int
  +24:  [B] b3 : float
  +36:  [C] c1 : class java.lang.Object
  +28:  [C] c2 : float
  +32:  [C] c3 : int
  +40:  [D] d1 : class java.lang.Object
  +44:  [D] d2 : int

The changeset that introduced this new feature was made in April, 2010. http://hg.openjdk.java.net/jdk6/jdk6/hotspot/rev/b9d85fcdf743

Update: It works on 6u25 Linux x64, but not on 6u25/6u26 Windows x86.

import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class ObjectLayouts {
public static void printStaticFieldOffsets(Class<?> clazz)
throws Exception {
if (clazz == null) {
System.err.println("got null pointer, skipping");
return;
}
System.out.printf("Static field offsets for class %s:\n", clazz.getName());
printStaticFieldOffsets0(clazz);
}
private static void printStaticFieldOffsets0(Class<?> clazz)
throws Exception {
if (clazz == null) return;
printStaticFieldOffsets0(clazz.getSuperclass());
Unsafe unsafe = getUnsafe();
for (Field f : clazz.getDeclaredFields()) {
if (Fields.isStatic(f)) {
long offset = unsafe.staticFieldOffset(f);
System.out.printf(" +%d:\t[%s] %s : %s\n",
offset, clazz.getName(), f.getName(), f.getType());
}
}
}
public static void printInstanceFieldOffsets(Class<?> clazz)
throws Exception {
if (clazz == null) {
System.err.println("got null pointer, skipping");
return;
}
System.out.printf("Instance field offsets for class %s:\n", clazz.getName());
printInstanceFieldOffsets0(clazz);
}
private static void printInstanceFieldOffsets0(Class<?> clazz)
throws Exception {
if (clazz == null) return;
printInstanceFieldOffsets0(clazz.getSuperclass());
Unsafe unsafe = getUnsafe();
for (Field f : clazz.getDeclaredFields()) {
if (!Fields.isStatic(f)) {
long offset = unsafe.objectFieldOffset(f);
System.out.printf(" +%d:\t[%s] %s : %s\n",
offset, clazz.getName(), f.getName(), f.getType());
}
}
}
private static Unsafe getUnsafe() throws Exception {
Class<?> unsafeClass = Unsafe.class;
for (Field f : unsafeClass.getDeclaredFields()) {
if ("theUnsafe".equals(f.getName())) {
f.setAccessible(true);
return (Unsafe) f.get(null);
}
}
return null;
}
}
[sajia@v036122 ~]$ export JAVA_OPTS='-XX:FieldsAllocationStyle=2'
[sajia@v036122 ~]$ groovysh
Groovy Shell (1.7.7, JVM: 1.6.0_25)
Type 'help' or '\h' for help.
----------------------------------------------------------------------------------------------------------------------------
groovy:000> import java.lang.management.ManagementFactory
===> [import java.lang.management.ManagementFactory]
groovy:000> import com.sun.management.HotSpotDiagnosticMXBean
===> [import java.lang.management.ManagementFactory, import com.sun.management.HotSpotDiagnosticMXBean]
groovy:000> HOTSPOT_BEAN_NAME = "com.sun.management:type=HotSpotDiagnostic"
===> com.sun.management:type=HotSpotDiagnostic
groovy:000> server = ManagementFactory.platformMBeanServer
===> com.sun.jmx.mbeanserver.JmxMBeanServer@460ab1b4
groovy:000> bean = ManagementFactory.newPlatformMXBeanProxy(server, HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean)
===> MXBeanProxy(com.sun.jmx.mbeanserver.JmxMBeanServer@460ab1b4[com.sun.management:type=HotSpotDiagnostic])
groovy:000> bean.getVMOption('FieldsAllocationStyle')
===> VM option: FieldsAllocationStyle value: 2 origin: VM_CREATION (read-write)
groovy:000> quit
[sajia@v036122 experiment]$ cd experiment/test_object_layout/
[sajia@v036122 test_object_layout]$ ls
A.class A.java B.class C.class Fields.class Fields.java ObjectLayouts.class ObjectLayouts.java
[sajia@v036122 test_object_layout]$ groovysh
Groovy Shell (1.7.7, JVM: 1.6.0_25)
Type 'help' or '\h' for help.
----------------------------------------------------------------------------------------------------------------------------
groovy:000> ObjectLayouts.printInstanceFieldOffsets(C)
Instance field offsets for class C:
+16: [A] aObj : class java.lang.Object
+12: [A] aInt : int
+20: [B] bObj : class java.lang.Object
+24: [B] bInt : int
+28: [B] bFloat : float
+36: [C] cObj : class java.lang.Object
+32: [C] cInt : int
===> null
groovy:000> quit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment