Java Virtual Machine
It's called a virtual machine for two reasons. It adds a layer between the Java app and the physical machine. And it has its own instruction set.
Instruction Set
A CPU has its own instruction set. The JVM has one too. The JVM then maps its instructions to the CPU's instructions.
When a Java class is compiled, you get a .class file. It has a set format that only the JVM can read.
The first byte of a .class file is always 0XCAFEBABE. It was chosen as a nod to coffee.
Stack Based Virtual Machine
It's a stack based virtual machine. It uses a stack to manage code execution. A stack frame stores state and local variables. It also controls the flow. Read code execution for more on how the stack is used.
Byte Code
It's called byte code because the Java code becomes instructions. Each one is a byte or more long.
Byte code is an in-between step. It enables dynamic resolution, such as SPI and runtime-provided classes. Direct native code would not allow such dynamic resolution and linking.
Size of Byte Code
Turning Java code into byte code also cuts the code size. Java code may look verbose. Still, the byte code stays small. It does this by heavy optimization and by removing redundancies.
The JVM itself is native compiled code. This native code turns Java's byte code into native code. Then it schedules that code to run.
Program Counter
A CPU has instruction pointers. The JVM has a program counter too. It points to the byte code address where interpretation must start. This value lives in the stack frame the interpreter uses to manage the flow. When a method returns, the previous stack frame knows where to continue from this.
Read about the byte code array in the class loading page to see how the program counter works.