The "byte code" is called an intermediary code between the source and the code that will get executed in your computer.
Your code gets translated to this intermediate language that the Java Virtual Machine understands. Its kinda a pseudo assembler, but instead of having x86 instructions, you have instructions for the JVM (think of it as a virtual processor which runs on top of your CPU).
The difference is that while assembly is compiled into an executable and runs directly on the CPU, the java byte code gets executed by the JVM. So this JVM translates the byte code into something the CPU in your computer can understand.
While on conventional languages you'd be compiling a separate executable for each architecture you're targeting (ie, one for x86, other for x86_64, etc), with managed languages (Java, C#, etc) you compile all the programs for a single target, the Virtual Machine, so you don't have to worry about the actual architecture which your program might get run on. Often you don't even have to worry about which OS your program gets run on either since developers try to abstract OS API specific calls in the standard libraries (say, you don't have to know how to create a window in Windows/OSX/Linux to create a window using Swing in Java).
The JVM does needs to be architecture specific since its the program in charge of actually running your Java bytecode in the environment of the user (CPU+OS). So you can't use a JVM for powerpc in a x86 CPU. The user has to install a working JVM to use your program (and any other program compiled for the JVM).
That's probably the main selling point of it. But as always, things aren't that simple and there are many ups and downs about using managed vs conventional languages. So beware of "what is better? C# or C++?" kind of questions because there isn't a simple all-encompassing answer for such things.