How C/C++, Java, and Python Run: A Deep Dive into Compilation and Execution
This article compares the execution models of C/C++, Java, and Python, explaining how compiled machine code, bytecode with JVM, and interpreted bytecode with the Python virtual machine operate, and illustrates each process with example file structures and compilation steps.
C/C++ Execution Model
C/C++ is a compiled language. Before execution, a compiler translates the source code directly into machine code, which runs on the CPU. It is a static language because variable types are determined at compile time. This model aims for maximum performance and is commonly used for operating systems, game engines, and other performance‑critical software.
Assume a C project containing three source files a1.c, a2.c, and a3.c with functions main(), f1(), and f2(). The compiler first compiles each .c file into an object file ( .obj). The linker then combines the three object files into an executable ( .exe). At runtime, a program loader loads the .exe into RAM and the CPU executes the native machine code directly.
Java Execution Model
Java is a hybrid compiled‑and‑interpreted language. The Java compiler first compiles source files into bytecode ( .class files). At runtime, the Java Virtual Machine (JVM) loads these class files, verifies the bytecode for safety, and then executes it. The JVM performs just‑in‑time (JIT) compilation, translating bytecode into native machine code on the fly. Like C/C++, Java is statically typed because types are fixed at compile time, but the additional JVM layer introduces some performance overhead while providing cross‑platform portability.
Assume three Java source files a1.java, a2.java, and a3.java with the same functions as the C example. The Java compiler produces three .class files. The JVM’s class loader loads them into RAM, the bytecode verifier checks them, and the execution engine JIT‑compiles them to native code before execution.
Python Execution Model
Python is an interpreted language. Its source code is not compiled ahead of time; instead, the Python interpreter first compiles each .py file into bytecode ( .pyc) and caches it. The default interpreter, CPython, then executes the bytecode with the Python Virtual Machine (PVM). Because the compilation happens at runtime, variable types are determined dynamically.
Assume three Python scripts a1.py, a2.py, and a3.py. a1.py defines a __main__ entry that imports a2.py and a3.py. When a1.py is run, the interpreter compiles it to a1.pyc. If an import is encountered, compilation of the current file pauses, the imported file is compiled to its own .pyc, and then execution resumes. After all dependent bytecode files are prepared, the PVM executes them line by line, producing the program’s output.
Python has multiple interpreter implementations, such as CPython (the official reference implementation), Jython, and PyPy. CPython is the most widely used.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
