Search code examples
javajol

Does Java Object Layout work with Java Records?


I'm attempting to use Java Object Layout (JOL) to measure the instance size of an object that holds onto instances of some Java Records. I am getting an UnsupportedOperationException with a description "can't get field offset on a record class" when using GraphLayout.parseInstance. I get the same error when using ClassLayout.parseClass.

I was initially using Java 20, but have downgraded to Java 17. I tried the last two versions of JOL (0.17 and 0.16). I tried the recommendation from the stack trace "Cannot get the field offset, try with -Djol.magicFieldOffset=true". It looks like Records are not supported in HotspotUnsafe.fieldOffset and specifically at line 647 in Unsafe.

Here's an example of a class that passes and similar record that throws the exception.

public class Outer {
    public static void main(String[] args) {
        // Passes - outputs 72
        System.out.println(GraphLayout.parseInstance(new A(1, "one")).totalSize());

        // Fails with UnsupportedOperationException
        // "can't get field offset on a record class: private final int Outer$B.value"
        // sun.misc.Unsafe.objectFieldOffset - line 648
        System.out.println(GraphLayout.parseInstance(new B(1, "one")).totalSize());
    }

    public static class A {
        int value;
        String name;

        public A(int value, String name) {
            this.value = value;
            this.name = name;
        }
    }

    public static record B(int value, String name) {
    }
}

I did some searching to find examples of using JOL with Java Records but did not find anything. Is this possible with JOL currently, using some configuration settings I may have missed?


Solution

  • The answer is Yes, Java Object Layout does work with Java Records and requires the option -Djol.magicFieldOffset=true to be passed on the command line. According to Aleksey, this option was added specifically to work with records.

    I was running the code from IntelliJ and was setting the option in program arguments text box instead of vmoptions text box (which I had to add first). Adding the option to vmoptions in Run/Debug Configurations fixed the issue.