Code is probably better than words.
What can be done with a bit of hackery
import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import sun.misc.Unsafe;
public class MappedObject {
static Unsafe unsafe;
static Field addressHack;
static {
try {
ByteBuffer bb = ByteBuffer.allocateDirect(1);
Field unsafeHack = bb.getClass().getDeclaredField("unsafe");
unsafeHack.setAccessible(true);
unsafe = (Unsafe) unsafeHack.get(bb);
addressHack = Buffer.class.getDeclaredField("address");
addressHack.setAccessible(true);
} catch (Exception exc) {
exc.printStackTrace();
}
}
private long base;
public final void attach(ByteBuffer bb, int offset) {
try {
base = addressHack.getLong(bb) + offset;
} catch (Exception exc) {
exc.printStackTrace();
throw new InternalError();
}
}
public int getY() {
return unsafe.getInt(base + 8);
}
public void setY(int y) {
unsafe.putInt(base + 8, y);
}
public int getX() {
return unsafe.getInt(base + 16);
}
public void setX(int x) {
unsafe.putInt(base + 16, x);
}
public static void main(String[] argv) {
MappedObject mo = new MappedObject();
ByteBuffer bb = ByteBuffer.allocateDirect(1000);
mo.attach(bb, 128);
mo.setY(1);
for (int i = 0; i < 500; i++) {
test(mo);
}
System.out.println(mo.getX());
}
private static void test(MappedObject mo) {
for (int i = 0; i < 1000000; i++) {
mo.setX(mo.getY() + mo.getX());
}
}
}
And this is how inner stride of loop inside test method looks like
040 B4: # B4 B5 <- B3 B4 Loop: B4-B4 inner stride: not constant Freq: 7.51066
040 MOV EDI,[EAX + #8]
043 ADD ECX,EDI
045 MOV [EAX + #16],ECX
048 INC EBX
049 CMP EBX,#1000000
04f Jlt,s B4 P=1.000000 C=7.509333
When playing with this code, I have seen once that hotspot unrolled this inner loop by 4, but I was not able to reproduce it, for whatever reasons.
I think it clearly shows, that it is perfectly possible to write well performing struct class using today jvm. Only problem is that you have to use getter/setter instead of direct field access - which can be a clarity issue, but doesn’t affect the performance in slightest way.
MappedObject class would have to be made abstract, with subclasses for specific structures. It also requires full rights in jvm and performs no checks currently - but a adding check in attach would be exactly what you mentioned and should not affect the performance.