(This is all from the Microsoft CLI common source, it has the CLR source code.)
If you look at clr\src\vm\object.h , you will see:
// The generational GC requires that every object be at least 12 bytes in size.
which is pretty clear. In addition, in clr\src\vm\gcscan.cpp you can see expressions such as
_ASSERTE(g_pObjectClass->GetBaseSize() == MIN_OBJECT_SIZE);
or
_ASSERTE(totalSize < totalSize + MIN_OBJECT_SIZE);
which, I think, explains why you see the unexpected size of the object. :)
Update:
@ She had a great point in the sync block; I just want to point out the subtlety once again confirmed in object.h :
class Object { protected: MethodTable* m_pMethTab;
Pay attention to this part:
The index of the synchronization block is actually at a negative offset .
Thus, the synchronization block, apparently, does not actually follow the method table (as Hans mentioned), but it does reach it - so this is not the “normal” part of the object (due to the lack of a better word).
Mehrdad
source share