I'll start with your last question: It does know the size of objects - this size is passed to the GC when you allocate memory from it. Root ranges (such as the stack, global variables, TLS areas, etc) also all have a static size.
(Not strictly true - some runtimes have dynamically growing stacks, but the GC knows the size regardless.)
Most garbage collectors assume pointers to be aligned on a word boundary; that is on a 4-byte boundary on 32-bit machines and an 8-byte boundary on 64-bit machines. This is a reasonable assumption because accessing pointers that are not word-aligned is extremely slow on most architectures. It does not care how fields that don't contain pointers are aligned because their contents are irrelevant (so this translates to the compiler being able to pack some fields together without worrying about breaking the GC).
So, a conservative GC will simply scan over every word in an object and interpret it as a potential pointer, regardless of what it actually is. So yes - even a double will be considered a pointer.
(Not strictly true - some runtimes have dynamically growing stacks, but the GC knows the size regardless.)
Most garbage collectors assume pointers to be aligned on a word boundary; that is on a 4-byte boundary on 32-bit machines and an 8-byte boundary on 64-bit machines. This is a reasonable assumption because accessing pointers that are not word-aligned is extremely slow on most architectures. It does not care how fields that don't contain pointers are aligned because their contents are irrelevant (so this translates to the compiler being able to pack some fields together without worrying about breaking the GC).
So, a conservative GC will simply scan over every word in an object and interpret it as a potential pointer, regardless of what it actually is. So yes - even a double will be considered a pointer.