Just to compare, let's take a look at a language that doesn't enforce a single root class - Objective-C. In most Objective-C environments there will be three root classes available (Object, NSObject and NSProxy), and you can write your own root class by just not declaring a superclass. In fact Object is deprecated and only exists for legacy reasons, but it's informative to include it in this discussion. The language is duck typed, so you can declare a variable's type as "any old object" (written as id), then it doesn't even matter what root class it has.
OK, so we've got all of these base classes. In fact, even for the compiler and runtime libraries to be able to get anywhere they need some common behaviour: the root classes must all have a pointer ivar called isa that references a class definition structure. Without that pointer, the compiler doesn't know how to create an object structure, and the runtime library won't know how to find out what class an object is, what its instance variables are, what messages it responds to and so forth.
So even though Objective-C claims to have multiple root classes, in fact there's some behaviour that all objects must implement. So in all but name, there's really a common primitive superclass, albeit one with less API than java.lang.Object.
N.B. as it happens both NSObject and NSProxy do provide a rich API similar to java.lang.Object, via a protocol (like a Java interface). Most API that claims to deal with the id type (remember, that's the "any old object" type) will actually assume it responds to messages in the protocol. By the time you actually need to use an object, rather than just create it with a compiler, it turns out to be useful to fold all of this common behaviour like equality, hashing, string descriptions etc. into the root class.