← Back to list

Java Learning Journey: Introduction and Overview of Java

Java Internals

Oluwatobiloba Olamide · 2026-04-26 17:53 · 4 claps · 6.0 min read
#java #java-internals #java-programming #compilers #interpreters
Open on Medium ↗
Wiki topics: EDU · Education & Learning 💻 · Programming

Java Learning Journey: Introduction and Overview of Java

Java Internals

Introduction

If you’ve ever wondered how apps like Spotify, LinkedIn, or even your banking app were built, there’s a good chance Java had something to do with it. Java is one of the most widely used programming languages in the world and for good reason. It’s powerful, flexible, beginner-friendly, and runs virtually everywhere.

Programming Language

Before we get into Java specifically, it helps to understand the landscape of programming languages because not all languages are created equal

Low-Level Languages

Low-level languages speak the computer’s native tongue. They deal directly with hardware things like memory locations and allocation.

There are two types:

  • Machine language: pure binary (0s and 1s). It’s the only language a CPU truly understands. Every program, no matter what language it was written in, eventually becomes machine language.
  • Assembly language: a step up from machine language. Instead of raw binary, you write short symbolic codes (like MOV, ADD, JMP). An assembler then converts this into machine language.
Assembly Language → Assembler → Machine Language

Low-level languages give you a lot of control and speed, but they are tedious and difficult to write. They’re not practical for large, complex applications.

High-Level Languages

High-level languages are much closer to how humans think and communicate. They use English-like words, mathematical notation, and clear structure hiding away all the messy low-level details like memory management.

Examples include: Fortran, C, C++, Java, and C#.

With a high-level language, you can focus on what you want the computer to do, rather than how it should do it at the hardware level. That’s a huge productivity win.

To run a high-level program, it must first be translated into machine language. This brings us to compilation.

Compilation

When you write code in a high-level language, a special program called a compiler translates your source code into a target language.

Source Code → Compiler → Target Language

That target language can be:

  • Machine code (binary — runs directly on hardware)
  • Bytecode (an intermediate form — more on this shortly)
  • Another programming language (when this happens, the compiler is called a transpiler or source-to-source compiler)

Java uses a fascinating combination of compilation and interpretation which is a big part of what makes it so powerful.

What is Java?

Java is a general-purpose, high-level programming language created by Sun Microsystems in 1995 (now owned by Oracle). It was built with a simple but ambitious philosophy:

“Write Once, Run Anywhere.”

Core Characteristics Of Java

  • General purpose: Used for web apps, mobile, enterprise software, and more
  • Object-oriented: Organises code into reusable “objects”
  • Platform independent: The same Java code runs on Windows, Mac, Linux
  • Concurrent: Can handle multiple tasks at the same time
  • Very fast: Optimised execution through JIT compilation
  • Automatic memory management: Java handles memory cleanup for you

Java’s Core Goals

When Java was designed, the engineers had clear goals in mind:

  • Consume less memory: efficient use of system resources
  • Delivery of software components: modular, reusable code
  • Platform independence: code runs everywhere without modification
  • Security: built-in protection mechanisms
  • Multithreading: efficient handling of concurrent operations

Platform Independence

This is where Java gets really interesting. How exactly does the same Java code run on a Windows PC, a Mac, a Linux server, or an Android phone?

The answer is the Java Virtual Machine (JVM).

The Problem: Platform Dependency

Different operating systems and hardware have their own quirks:

  • Operating systems differ in executable file formats and system calls (e.g. how Linux opens a file is different from how Windows does it)
  • Hardware differs in instruction sets (e.g. Intel’s x86 architecture vs ARM used in smartphones)

A program compiled for Windows won’t just run on Linux. Traditionally, developers had to rewrite or recompile their code for each platform.

The Solution: Bytecode + JVM

Java solves this with a two-step approach:

Java Source Code (.java)
        ↓
Java Compiler
        ↓
Bytecode (.class) ← Platform independent
        ↓
JVM (platform-specific) ← Runs the bytecode
        ↓
Program executes
  1. Your Java source code is compiled into bytecode a compact, optimised, intermediate format. Bytecode is platform independent, meaning it’s the same .class file whether you're on Mac or Windows.
  2. The JVM (which is platform-specific and installed separately for each OS) reads and executes the bytecode.

Think of bytecode as a universal script, and the JVM as a translator that speaks the local language of whatever computer it’s installed on.

Point to remember:

  • Java bytecode is platform independent
  • The JVM is platform dependent

This also means bytecode is compact enough to transfer quickly across a network which was a major design consideration when the internet was young.

The JVM (Java Virtual Machine)

The JVM is an abstract computing machine a software-based CPU that runs Java bytecode. It’s the heart of Java’s “run anywhere” promise.

What the JVM Does

  • Loads and interprets Java bytecode
  • Manages memory automatically (garbage collection)
  • Enforces security
  • Optimises performance

JVM Architecture

┌─────────────────────────────────────────┐
│              JVM                        │
│                                         │
│  ┌─────────────┐  ┌──────────────────┐  │
│  │ Class Loader│  │ Bytecode Verifier│  │
│  └─────────────┘  └──────────────────┘  │
│                                         │
│  ┌──────────────────────────────────┐   │
│  │      Runtime Data Area           │   │
│  │         (JVM Memory)             │   │
│  └──────────────────────────────────┘   │
│                                         │
│  ┌──────────────────────────────────┐   │
│  │       Execution Engine           │   │
│  │  ┌──────────────┐ ┌───────────┐  │   │
│  │  │ Interpreter  │ │  JIT      │  │   │
│  │  │              │ │ Compiler  │  │   │
│  │  └──────────────┘ └───────────┘  │   │
│  └──────────────────────────────────┘   │
│                                         │
│  ┌──────────────┐  ┌─────────────────┐  │
│  │  Garbage     │  │ Security Manager│  │
│  │  Collector   │  │                 │  │
│  └──────────────┘  └─────────────────┘  │
└─────────────────────────────────────────┘
  • Class Loader: loads .class files (bytecode) into memory
  • Bytecode Verifier: checks bytecode is valid and safe before execution
  • Runtime Data Area: the JVM’s memory workspace
  • Execution Engine: runs the bytecode (using the interpreter and JIT compiler)
  • Garbage Collector: automatically reclaims memory no longer in use
  • Security Manager: enforces Java’s security policies

The Interpreter and JIT Compiler

The JVM’s execution engine has two weapons for running bytecode: the Interpreter and the JIT Compiler. Together, they balance speed and platform independence.

The Interpreter

The interpreter works like a virtual CPU it simulates the fetch-and-execute cycle:

  1. Fetch: get the next program statement
  2. Understand: decode what the statement means
  3. Execute: run precompiled machine code from its library

The interpreter runs every statement line by line. It’s flexible but can be slow, because it re-reads and re-translates the same code every time it runs.

Advantages of interpretation:

  • Platform independence (same bytecode, different interpreters per OS)
  • No separate compilation step needed at runtime
  • Easier to update and deploy

Disadvantages:

  • Slower execution
  • Higher memory cost (interpreter itself must be loaded into memory)
  • Source/bytecode is re-interpreted on every run

Just-In-Time (JIT) Compilation

The JIT compiler is Java’s performance booster.

  1. It monitors the running program to identify “hot spots” sections of bytecode that are executed frequently
  2. It compiles those hot spots directly into native machine code
  3. That machine code is cached, so next time the same section runs, it executes at full native speed no interpretation needed

This is also called dynamic compilation, because it happens at runtime, not before the program runs.

The JIT compiler is why Java is described as “very fast” despite being interpreted. You get the portability of bytecode and the performance of compiled code.

Structure of a Java Program

Now that we understand how Java works, let’s look at how a Java program is actually organised.

Everything Lives in a Class

In Java, all code is written inside a class. A class is a blueprint — a container that holds related data and behaviour together.

A class can contain:

  • Variable declarations: data the class stores
  • Constructors: special methods that set up the object when it’s created
  • Statements: individual instructions
  • Method statements: blocks of reusable code (functions)
  • Nested classes: classes defined inside another class

The main() Method

Every Java application has a starting point: the main() method. When you run a Java program, the JVM:

  1. Loads the bytecode of your .class file into memory
  2. Locates the main() method
  3. Begins executing from there
  4. The program ends when main() finishes
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

Rules for main() Method

The main() method has strict rules it must be declared as:

  • **public:**accessible from anywhere (the JVM needs to call it)
  • **static**:can be called without creating an object of the class
  • **void:**it doesn't return any value
public static void main(String[] args) { ... }

From inside main(), you invoke all the other code in your program. The program starts with main()and ends with it too.

Conclusion

Learning a programming language is an investment and Java is one that pays dividends for years.

Java isn’t just another language you study for a course and forget. It powers some of the largest systems on the planet from Android apps used by billions, to the backend of enterprise banking platforms, to massive distributed systems at companies like Amazon and LinkedIn. When you learn Java, you’re learning a skill that is actively in demand across industries, geographies, and specialisations.


메타데이터
post_id
dcb730a756b3
slug
java-learning-journey-introduction-and-overview-of-java-dcb730a756b3
url
https://medium.com/@oluwateezzy03/java-learning-journey-introduction-and-overview-of-java-dcb730a756b3
canonical_url
https://medium.com/@oluwateezzy03/java-learning-journey-introduction-and-overview-of-java-dcb730a756b3
author_url
https://medium.com/@oluwateezzy03
status
ok
fetched_at
2026-07-31 10:40:39