It's both. The javac compiler compiles .java files into .class files (which contain so-called bytecode, which is cross-platform compatible). The JVM then interprets the bytecode (and may compile some of it into native code).
If you're interested in the details, then the JVM specification has lots of interesting stuff.
Most modern JVMs are based on Hotspot technology. This means that when a class is first used, it will be interpreted, until the natively compiled version is ready.
Furthermore, it will also track the program while it is running, and tune optimization as needed. It will even go back and adaptively recompile portions of the code as necessary to optimize the code (based on usage patterns).
This last part is where it gets it's name "hotspot". It will adaptively optimize the parts of the code that runs repeatedly.
Henry [ February 03, 2007: Message edited by: Henry Wong ]