jextract: offset not multiple of alignment, causing ExceptionInInitializerError

Sebastian Stenzel sebastian.stenzel at gmail.com
Fri Jan 15 08:31:17 UTC 2021


I had another look at the original header file (macOS: usr/include/sys/fcntl.h). Turns out, this struct is surrounded by a pack(4), which should explain this behaviour:

#pragma pack(4)

struct log2phys {
        unsigned int    l2p_flags;       /* unused so far */
        off_t           l2p_contigbytes; /* F_LOG2PHYS:     unused so far */
                                         /* F_LOG2PHYS_EXT: IN:  number of bytes to be queried */
                                         /*                 OUT: number of contiguous bytes at this position */
        off_t           l2p_devoffset;   /* F_LOG2PHYS:     OUT: bytes into device */
                                         /* F_LOG2PHYS_EXT: IN:  bytes into file */
                                         /*                 OUT: bytes into device */
};

#pragma pack()

Question is: Is jextract _expected_ to be aware of this?


> On 14. Jan 2021, at 23:01, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
> 
> That layout looks odd/wrong.
> 
> It seems like there might be some padding missing. Note that you have a 64 bit field that is not 64 bit aligned - so accessing it might be slower. I believe in most compilers 32 bit of padding would be inserted.
> 
> Or, if this is really the way the struct is laid out, jextract should have relaxed the alignment requirements for "l2p_contigbytes". As it stands, the jextract layout seems bogus. If you have access to the code, I'd suggest adding:
> 
> C_LONG_LONG.withName("l2p_contigbytes").withAlignmentBits(32)
> 
> This should allow you to initialize correctly.
> 
> Maurizio
> 
> On 14/01/2021 21:34, Sebastian Stenzel wrote:
>> Hey,
>> 
>> Today I noticed a strange problem related to the MemoryLayout generated by jextract for the following struct:
>> 
>> ```
>> struct log2phys {
>> 	u_int32_t	l2p_flags;	
>> 	off_t		l2p_contigbytes;
>> 	off_t		l2p_devoffset;
>> };
>> ```
>> 
>> The generated layout looks like this:
>> 
>> ```
>> static final MemoryLayout log2phys$struct$LAYOUT_ = MemoryLayout.ofStruct(
>>         C_INT.withName("l2p_flags"),
>>         C_LONG_LONG.withName("l2p_contigbytes"),
>>         C_LONG_LONG.withName("l2p_devoffset")
>>     ).withName("log2phys");
>> ```
>> 
>> During runtime, when the class was loaded and the VarHandle for "l2p_contigbytes" was created, I got the following exception:
>> 
>> Exception in thread "main" java.lang.ExceptionInInitializerError
>> 	at com.example.fuse_h$fuse_operations.$LAYOUT(fuse_h.java:14808)
>> 	at com.example.fuse_h$fuse_operations.allocate(fuse_h.java:16294)
>> 	...
>> Caused by: java.lang.UnsupportedOperationException: Invalid alignment requirements for layout b64(l2p_contigbytes)[abi/kind=LONG_LONG,layout/name=l2p_contigbytes]
>> 	at jdk.incubator.foreign/jdk.internal.foreign.LayoutPath.checkAlignment(LayoutPath.java:273)
>> 	at jdk.incubator.foreign/jdk.internal.foreign.LayoutPath.dereferenceHandle(LayoutPath.java:159)
>> 	at jdk.incubator.foreign/jdk.incubator.foreign.MemoryLayout.lambda$varHandle$2(MemoryLayout.java:488)
>> 	at jdk.incubator.foreign/jdk.incubator.foreign.MemoryLayout.computePathOp(MemoryLayout.java:538)
>> 	at jdk.incubator.foreign/jdk.incubator.foreign.MemoryLayout.varHandle(MemoryLayout.java:488)
>> 	at com.example.fuse_h_constants_1.<clinit>(fuse_h_constants_1.java:1921)
>> 	... 5 more
>> 
>> I set a breakpoint at LayoutPath.checkAlignment and can tell that "l2p_contigbytes" has an offset of 32 bit (sounds reasonable) but an alignment of 64 bit. I have no idea, what all this means, but apparently it is invalid.
>> 
>> I were able to avoid this error in my test project, but I thought I'd better report this in case there is something wrong, as I can see nothing special about aforementioned struct.
>> 
>> Let me know if I can provide any further information!
>> 
>> Sebastian



More information about the panama-dev mailing list