The Java compiler (javac) translates Java instructions into instructions in a language called Java Byte Code (JBC).
The Java virtual machine (JVM) executes JBC instructions.
JVM is a stack machine. Most JBC instructions consist of a single operator. The arguments for the operator are assumed to be on an operands stack. When the instruction is executed, the arguments are replaced by the result.
For example, the sequence of instructions pushes 6 and 7 onto the operands stack, then replaces them by their product, 42:
ldc 6
ldc 7
imul
See The JVM for details.
To get an idea of how stack machines work, let's implement one in Java.
Here's a UML diagram showing the basic design:
We take advantage of the fact that the Java library already contains a Stack class. If our StackMachine class extends Stack<Double>, then we only need to add arithmetic methods.
Each arithmetic method will replace the top two doubles on the stack by the result of combining them arithmetically.
We will throw exceptions if the stack does not contain enough numbers to complete the desired operation.
We will add a simple test driver with a static main method.
Next we add a console user interface.
Finally we add a graphical user interface.
Note that the StackMachine class is independent of all user interfaces (i.e., the "uses" arrows are one-way.) Generally speaking, program data and logic should always be independent of presentation (user interface).