DEV Community

Cover image for Compilation vs Interpretation
Shankar L
Shankar L

Posted on

Compilation vs Interpretation

Compilation vs Interpretation

Why should you care?

You write code in a programming language such as Java, Python, C, or JavaScript.

But the CPU does not understand these languages directly.

Something has to translate your human-readable code into instructions the computer can execute.

That translation can happen in different ways.

Two of the most important concepts are:

  • Compilation
  • Interpretation

Understanding the difference helps you understand why programming languages behave differently, why some programs start quickly, why some run faster, and where tools such as the JVM and JIT compiler fit into the picture.


The Problem

Consider this simple program:

print("Hello World")
Enter fullscreen mode Exit fullscreen mode

The CPU cannot directly execute:

print("Hello World")
Enter fullscreen mode Exit fullscreen mode

It needs instructions that match the CPU's instruction set.

So we need a translation process.

There are two traditional approaches:

Source Code
    ↓
Compiler
    ↓
Machine Code
    ↓
CPU
Enter fullscreen mode Exit fullscreen mode

and:

Source Code
    ↓
Interpreter
    ↓
Execution
Enter fullscreen mode Exit fullscreen mode

But modern programming languages are more complicated than this simple distinction suggests.


The Concept

Compilation

A compiler translates source code into another form before the program runs.

A simplified C compilation process looks like:

C Source Code
      ↓
Compiler
      ↓
Machine Code
      ↓
Executable
      ↓
CPU
Enter fullscreen mode Exit fullscreen mode

For example:

int result = 10 + 20;
Enter fullscreen mode Exit fullscreen mode

A compiler can translate this into machine instructions appropriate for the target CPU.

The resulting executable can then be run without recompiling the source code every time.


Interpretation

An interpreter executes a program by reading and processing its instructions at runtime.

A simplified model is:

Source Code
      ↓
Interpreter
      ↓
Execute
      ↓
Next instruction
      ↓
Execute
Enter fullscreen mode Exit fullscreen mode

Python is commonly described as an interpreted language, although modern Python implementations first compile source code into bytecode before executing it.

This is an important distinction:

"Compiled" and "interpreted" describe execution strategies, not permanent categories that every language fits into perfectly.


Simple Explanation

Think about translating a book.

Compilation

Imagine translating the entire book into another language before giving it to the reader.

Entire book
    ↓
Translator
    ↓
Translated book
    ↓
Reader
Enter fullscreen mode Exit fullscreen mode

The translation happens beforehand.

Interpretation

Now imagine a translator sitting next to the reader and translating each sentence as the reader encounters it.

Sentence
   ↓
Translator
   ↓
Reader
   ↓
Next sentence
Enter fullscreen mode Exit fullscreen mode

The translation happens during reading.

That is the basic difference.


Real-world Analogy

Imagine a restaurant menu written in French.

Compilation

You translate the entire menu into English before customers arrive.

Every customer can immediately read the translated version.

Interpretation

A translator stands beside each customer and translates each item when they ask about it.

The first approach requires preparation.

The second approach performs translation during interaction.

Programming language execution has similar trade-offs.


Code Example

Consider this simple C program:

#include <stdio.h>

int main() {
    int a = 10;
    int b = 20;

    printf("%d\n", a + b);

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

With a compiler such as GCC, you can compile it:

gcc main.c -o main
Enter fullscreen mode Exit fullscreen mode

This produces an executable.

You can then run:

./main
Enter fullscreen mode Exit fullscreen mode

The general process is:

main.c
  ↓
GCC
  ↓
Executable
  ↓
CPU
Enter fullscreen mode Exit fullscreen mode

Now consider Python:

a = 10
b = 20

print(a + b)
Enter fullscreen mode Exit fullscreen mode

You normally run it with:

python main.py
Enter fullscreen mode Exit fullscreen mode

The Python runtime handles the execution process.

The important point is that the details are more nuanced than simply saying:

C = compiled
Python = interpreted
Enter fullscreen mode Exit fullscreen mode

Modern language implementations often combine several techniques.


Java Is Different

Java provides one of the clearest examples of a hybrid execution model.

When you write:

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}
Enter fullscreen mode Exit fullscreen mode

You compile it with:

javac Main.java
Enter fullscreen mode Exit fullscreen mode

The compiler produces:

Main.class
Enter fullscreen mode Exit fullscreen mode

This contains Java bytecode.

The process becomes:

Java Source
    ↓
javac
    ↓
Bytecode
    ↓
JVM
    ↓
Machine Code
    ↓
CPU
Enter fullscreen mode Exit fullscreen mode

The JVM can interpret bytecode and can also use a Just-In-Time compiler, commonly called a JIT compiler, to compile frequently executed code into native machine instructions at runtime.

This gives Java a mixture of compilation and interpretation techniques.


Common Mistakes

Mistake 1: "Compiled languages are always faster"

Not necessarily.

Performance depends on:

  • Compiler optimizations
  • Runtime behavior
  • CPU architecture
  • Memory access
  • Garbage collection
  • Algorithms
  • Data structures
  • Workload

A language's execution model is only one part of performance.


Mistake 2: "Python is purely interpreted"

This is an oversimplification.

For example, CPython typically performs:

Python Source
     ↓
Bytecode
     ↓
Python Virtual Machine
     ↓
Execution
Enter fullscreen mode Exit fullscreen mode

So even Python involves a compilation step.


Mistake 3: "Java is interpreted"

Saying Java is simply interpreted is also incomplete.

Java uses:

Source
  ↓
Bytecode
  ↓
JVM
  ↓
Interpreter and/or JIT Compiler
  ↓
Machine Code
Enter fullscreen mode Exit fullscreen mode

The JVM can dynamically optimize frequently executed code.


Mistake 4: "Compilation happens only once"

It depends on the language and execution environment.

Traditional compiled programs may be compiled before distribution.

JIT compilation happens while the program is running.

Therefore, compilation can happen both before and during execution.


Advanced Notes

Ahead-of-Time Compilation

AOT compilation means code is compiled before execution.

The general process is:

Source
  ↓
Compiler
  ↓
Native Machine Code
  ↓
Execution
Enter fullscreen mode Exit fullscreen mode

C and C++ commonly use this model.

Advantages include:

  • Fast startup
  • Strong compile-time optimization
  • Direct native execution

Just-In-Time Compilation

JIT compilation happens while the program is running.

A simplified process is:

Source
   ↓
Intermediate Representation
   ↓
Runtime
   ↓
JIT Compiler
   ↓
Machine Code
Enter fullscreen mode Exit fullscreen mode

The runtime can observe how the program behaves and optimize frequently executed code.

This is used by technologies such as:

  • JVM
  • .NET runtime
  • JavaScript engines

Bytecode

Bytecode is an intermediate representation.

It sits between source code and machine code.

For Java:

Java Source
    ↓
Java Bytecode
    ↓
JVM
    ↓
Machine Code
Enter fullscreen mode Exit fullscreen mode

The advantage is portability.

The same Java bytecode can run on different operating systems and CPU architectures as long as a compatible JVM exists.

This is the idea behind:

Write once, run anywhere.


Compilation vs Interpretation

Feature Compilation Interpretation
Translation Before or during build During execution
Typical output Machine code or intermediate code Runtime execution
Startup Often faster after compilation Can have runtime overhead
Optimization Can happen before execution Can happen dynamically
Examples C, C++ Traditional interpreters
Modern reality Often combined with other techniques Often combined with bytecode/JIT

The table is intentionally simplified because modern runtimes frequently combine compilation, interpretation, bytecode, and JIT techniques.


The Bigger Picture

The most useful mental model is not:

Compiled vs Interpreted
Enter fullscreen mode Exit fullscreen mode

Instead, think:

How does this language implementation
transform source code into executable work?
Enter fullscreen mode Exit fullscreen mode

Different languages can choose different strategies.

For example:

C
Source
  ↓
Compiler
  ↓
Native Machine Code
Enter fullscreen mode Exit fullscreen mode
Java
Source
  ↓
Bytecode
  ↓
JVM
  ↓
JIT
  ↓
Machine Code
Enter fullscreen mode Exit fullscreen mode
Python
Source
  ↓
Bytecode
  ↓
Python Runtime
  ↓
Execution
Enter fullscreen mode Exit fullscreen mode
JavaScript
Source
  ↓
JavaScript Engine
  ↓
Interpretation + JIT
  ↓
Machine Code
Enter fullscreen mode Exit fullscreen mode

The exact implementation depends on the runtime and version.


Summary

Compilation and interpretation are two different approaches for turning source code into executable behavior.

Compilation

Source
  ↓
Compiler
  ↓
Machine Code
  ↓
CPU
Enter fullscreen mode Exit fullscreen mode

Interpretation

Source
  ↓
Interpreter
  ↓
Execution
Enter fullscreen mode Exit fullscreen mode

But modern systems are more sophisticated.

Java uses bytecode and the JVM.

Python implementations may compile source into bytecode.

JavaScript engines commonly combine interpretation and JIT compilation.

The most important lesson is:

Programming languages are not simply "compiled" or "interpreted." Their implementations can use multiple execution techniques.

Understanding this distinction gives you a much better foundation for learning compilers, virtual machines, programming language runtimes, and performance optimization.

Top comments (0)