The details are in the implementation (not the spec). However, the implementations generally follow a very simple pattern. Most of the memory layout in Java is very simple and straightforward. My terminology may not match the Java terminology, since I don't do a lot of Java programming.
In general, an object starts with a pointer to its vtable, and then has a bunch of fields that follow. Fields are either primitive types (int/bool/float) or pointers to objects. That's it for objects. (Classes are objects, too.) Null pointers are like C, they're invalid, not like Python, where None is an object.
In an inner class, there is an extra hidden field that points to an instance of the outer class. This is how inner classes access data in the outer class. Anonymous classes work the same way. Static methods are just methods on the class instead of methods on the instance.
The vtable is where all the magic happens. Each class has its own vtable shared between all the objects. The vtable has information about the class such as the size of its instances and how the fields are laid out. This information is used by the garbage collector. The vtable also has a pointers to all of the methods that the class implements. When you call a method, the runtime first grabs the vtable pointer out of the object, then grabs the method pointer out of the vtable, then calls the method and passes the object to the method as an implicit parameter. It's similar to C++, but much simpler to implement. The process can be skipped if the method or class is "final".
I know that Java doesn't really have "pointers", it has "symbolic handles" or somesuch, but the common implementations just use plain old pointers.