
Bytecode
Bytecode is an intermediate form of program code: it sits between the readable text that humans write and the instructions that a processor executes directly. A helper program on the target device reads the bytecode and converts it into real machine instructions there.
Programs are written by humans as text, in a programming language such as Java or Python. A processor, meaning the computing chip of a computer, does not understand this text. It only knows very simple instructions in a fixed numeric form, and this form differs for every chip type. Between these two worlds, a third layer is therefore often inserted: bytecode. This is a compact list of instructions that no human reads comfortably anymore, but that is also not yet tied to a specific chip. A helper program on the target device reads this list and executes it.
The name comes from the fact that the individual instructions traditionally occupy one byte each, a very small unit of storage. You can think of bytecode as a recipe in an artificial language. Nobody understands this language naturally, but there is an interpreter for it everywhere.
Why a program runs everywhere with it
Without an intermediate step, a program would have to be translated anew for every device type. A Windows PC, a Mac with an Apple chip, and an Android phone each understand different machine instructions. The manufacturer would therefore have to build and maintain several separate versions. With bytecode, only a single file is created, and every device brings its own translator along.
This is exactly what made Java big in the 1990s. The slogan was: write once, run anywhere. The same principle is found today in Python, in C#, and in WebAssembly, a bytecode format for web browsers. When a video editing program or a 3D game runs in the browser, WebAssembly is often behind it.
A second advantage is security. Because the bytecode is not directly unleashed on the chip, the translator can check beforehand what the program is even allowed to do. A browser thus blocks access to foreign files. The price for this is speed: this control costs computing time.
From source code to executed instruction
First, a compiler reads the written program text. A compiler is a translation program; it checks the text for errors and converts it into bytecode. This step happens once, at the developer’s end. In Java, this produces a file with the extension .class.
On the target device, a so-called virtual machine then takes over. This is not a real computer, but a program that behaves like one. It goes through the bytecode instruction by instruction and executes each one. An instruction might say, for instance: put the number 5 on the stack, or add the two topmost values.
Pure line-by-line processing would be slow. That is why modern systems use a just-in-time compiler. It observes which spots in the program run particularly often and translates exactly those into real machine instructions during execution. A common misconception is that bytecode is generally slow. For long-running programs, it now comes close to directly compiled code.
Bytecode in everyday life and in tech news
Anyone playing Minecraft in the Java Edition is starting bytecode. The same applies to many banking systems and to a large share of Android apps. Python works this way too: the first time a script is run, it quietly deposits files with the extension .pyc in a folder called __pycache__. This is the cached bytecode, so that the next start is faster.
In news reports, the term usually appears in three contexts. First, with WebAssembly, when it comes to fast applications in the browser. Second, with blockchain projects: contracts for Ethereum are translated into bytecode and executed identically by all computers in the network. Third, with security vulnerabilities, because attackers can inject manipulated bytecode.
Bytecode should be distinguished from two neighboring terms. Source code is the readable version that humans write and change. Machine code is the finished numeric form for a specific chip. Bytecode lies exactly in between and is thus neither well readable nor directly executable.