Let\'s assume this is about to happen in a true parallel environment, one VM, at the same time:
// Thread 1:
new Cat()
// Thread 2:
new Dog()
// Thread
This isn't specified in the Java specification. This means each JVM can do it however it wants to as long as it works and follows Java's memory guarantees.
A good guess on how this works with a moving GC, would be each thread gets its own allocation zone. Where it does a simple pointer increase when allocating objects. Very simple and very quick allocation with no locking. When that is full either it gets a new allocation zone allocated to it, or the GC moves all live objects to a continuous part of the heap and returns the now empty zones back to each thread. I am not sure if this is how it is actually implemented in any JVM, and it would be complicated with GC synchronization.