 Let's talk a little more about bits and bytes. As the book tells you, a byte is 8 bits, or binary digits. Here's a byte in binary. If we interpret it as an integer, it's the number 109. If we interpret it as an encoded character, it's the lowercase letter M. If we interpret those bits as a programming instruction on a 6502 processor, it's the instruction to add two numbers. This last part is important. Each pattern of bits is a different instruction to the CPU. This is called the CPU's instruction set. Every different type of CPU has a different instruction set or architecture. That means this pattern of bits, which is an add on a 6502, might mean jump to a different part of the program on an ARM processor or load an accumulator on an Intel processor. When we write a program in a high level language, it has to be translated into the bits and bytes for the CPU that's going to run the program. That translation process is called compiling. And for most languages, you need a different compiler for every architecture. The people who developed Java took a different and interesting approach. Instead of multiple versions of the compiler, there's one compiler that compiles to byte code. The instruction set for an idealized machine whose architecture is optimized for Java programs. This is the JVM, the Java Virtual Machine. Now, instead of having to write a new compiler that generates bits and bytes for every different architecture, which is very difficult, we write a program that takes the byte codes and implements them for the hardware we're running on. This is a much simpler task. Here's the workflow. You write your program in Java. You compile it to byte code and then run it on the JVM, the Java Virtual Machine. Once you have a working program, anyone with the Java runtime environment, which is the byte code interpreter, can run it.