Intro:
I used the JOL (Java Object Layout) tool to analyze the internal and external fragmentation of Java objects for research purpose.
While doing so, I stumbled across the following:
x@pc:~/Util$ java -jar jol-cli-0.9-full.jar internals sun.reflect.DelegatingClassLoader
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# WARNING | Compressed references base/shifts are guessed by the experiment!
# WARNING | Therefore, computed addresses are just guesses, and ARE NOT RELIABLE.
# WARNING | Make sure to attach Serviceability Agent to get the reliable addresses.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Instantiated the sample instance via sun.reflect.DelegatingClassLoader(java.lang.ClassLoader)
sun.reflect.DelegatingClassLoader object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 3b 13 00 f8 (00111011 00010011 00000000 11111000) (-134212805)
12 4 java.lang.ClassLoader ClassLoader.parent null
16 4 java.util.concurrent.ConcurrentHashMap ClassLoader.parallelLockMap null
20 4 java.util.Map ClassLoader.package2certs (object)
24 4 java.util.Vector ClassLoader.classes (object)
28 4 java.security.ProtectionDomain ClassLoader.defaultDomain (object)
32 4 java.util.Set ClassLoader.domains (object)
36 4 java.util.HashMap ClassLoader.packages (object)
40 4 java.util.Vector ClassLoader.nativeLibraries (object)
44 4 java.lang.Object ClassLoader.assertionLock (object)
48 4 java.util.Map ClassLoader.packageAssertionStatus null
52 4 java.util.Map ClassLoader.classAssertionStatus null
56 8 (alignment/padding gap)
64 1 boolean ClassLoader.defaultAssertionStatus false
65 7 (loss due to the next object alignment)
Instance size: 72 bytes
Space losses: 8 bytes internal + 7 bytes external = 15 bytes total
Question:
What's bothering me in this case is that every field is 4 byte aligned (see OFFSET column), but still at offset 56 an alignment gap gets added (56 8 (alignment/padding gap)
). I did the same test in Java 9, and there the object layout changed a little bit, the alignemnt/padding gap still exists, but is even 12 bytes large.
Why is this happening? And why is it 8 bytes large, all other objects I saw are 4-byte aligned interally? I couldn't find an explanation myself.
My system:
openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-0ubuntu0.16.04.2-b12)
OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)
Using default settings (ParallelOldGC with compressed oops)