Programming foundations: Java

Sefism.

Chapter 05

How computers run your code

Enough of what happens below your code that memory and number bugs stop surprising you: bits, text, the CPU, memory, compilers and the operating system.

Bits, bytes and binary

Also called binary, hexadecimal, hex

What
A bit is a 0 or 1. A byte is 8 bits and holds 256 values. Everything in a computer (numbers, text, images, code) is stored as bytes, and hexadecimal is a compact way to write them.
Why
It explains integer limits, file sizes, colours like #FF8800 and why data needs an agreed format to mean anything.
Example
The byte 01000001 is 65 in decimal and 0x41 in hex. Read as text in ASCII or UTF-8, it is the letter A.

Text encoding and Unicode

Also called UTF-8, ASCII, code points, UTF-16, Unicode

What
Unicode gives every character a number (a code point). An encoding such as UTF-8 turns code points into bytes: 1 byte for ASCII letters, up to 4 for others such as emoji.
Why
Length, slicing and file reading all depend on it. Mismatched encodings produce garbled text, and string lengths do not always equal visible characters.
Java
String s = "h茅llo 馃榾";
System.out.println(s.length()); // 8 UTF-16 units
System.out.println(s.codePointCount(0, s.length())); // 7
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
System.out.println(bytes.length); // 11

Watch out

Assuming one character is one byte, or one unit of string length, when cutting or measuring text.

How the CPU runs a program

Also called fetch-decode-execute, machine code, CPU cache

What
The CPU repeatedly fetches an instruction from memory, decodes it and executes it: simple steps such as add, compare, jump and copy. It keeps recently used data in small, very fast caches.
Why
Every line you write ends up as these steps. Cache behaviour explains why looping over an array is much faster than chasing pointers through a linked list.
Example
total += price becomes roughly: load total into a register, load price, add them, store the result back in memory.

Compiled and interpreted code

Also called compiler, interpreter, JIT, bytecode

What
A compiler translates source to machine code before running (C++). An interpreter runs code step by step (CPython runs bytecode). Java, C# and JavaScript engines compile to bytecode or directly, then JIT-compile hot code while running.
Why
It explains when errors appear (build time or run time), why start-up and speed differ, and why C++ needs a build for each platform.

Watch out

Calling a language "compiled" or "interpreted" as a fixed fact: it describes an implementation, and most modern runtimes mix both.

Stack and heap

Also called call stack, stack frame, heap memory, stack overflow

What
The stack holds each running function's local variables in frames that vanish when it returns. The heap holds objects that must outlive a call and is managed by a garbage collector or, in C++, by owners.
Why
It explains why deep recursion causes a stack overflow, why returning a pointer to a local is a bug in C++, and where your objects actually live.

Watch out

Recursing thousands of levels deep on large input, which overflows the stack even though the logic is correct.

Passing arguments to functions

Also called pass by value, pass by reference, pass by sharing

What
Python, JavaScript and Java always pass a copy of the value, but for objects that value is a reference, so the function can change the object but not rebind your variable. C++ and C# copy unless you pass by reference.
Why
It tells you whether a function can modify the list you give it, which is behind many "my data changed" and "my change vanished" bugs.
Java
static void addItem(List<String> items) {
  items.add("milk");
}
static void reset(List<String> items) {
  items = new ArrayList<>();
}

List<String> basket = new ArrayList<>(List.of("eggs"));
addItem(basket);
reset(basket);
System.out.println(basket); // [eggs, milk]

Watch out

Reassigning a parameter inside a function and expecting the caller's variable to change.

Garbage collection

Also called GC, reference counting, memory leak

What
The runtime frees heap objects automatically once nothing can reach them. CPython mostly uses reference counting plus a cycle collector; the JVM, .NET and JavaScript engines use tracing collectors.
Why
You rarely free memory by hand, but you still control what stays reachable. Leaks in these languages come from references you forgot to drop.

Watch out

Growing a global cache, list or event listener registry forever, which keeps every object in it alive.

Floating point numbers

Also called IEEE 754, float, double, rounding error

What
Floats store numbers in binary with limited precision, so most decimal fractions such as 0.1 are approximations. Small errors appear in arithmetic and comparisons.
Why
It is why 0.1 + 0.2 is not exactly 0.3, and why money should use integer cents or a decimal type.
Java
System.out.println(0.1 + 0.2); // 0.30000000000000004
System.out.println(0.1 + 0.2 == 0.3); // false
var a = new BigDecimal("0.1");
var b = new BigDecimal("0.2");
System.out.println(a.add(b)); // 0.3

Watch out

Comparing floats with ==, or storing money in a float or double.

Integer overflow

Also called wraparound, MAX_VALUE, BigInt

What
Fixed-size integers have a maximum. Going past it wraps around in Java and C#, is undefined behaviour for signed integers in C++, and loses precision in JavaScript numbers. Python integers grow without limit.
Why
Counters, timestamps in milliseconds, ids and money totals can exceed 32-bit limits; choosing a wide enough type avoids silent wrong answers.
Java
int max = Integer.MAX_VALUE;
System.out.println(max + 1); // -2147483648
long safe = (long) max + 1;  // 2147483648
Math.addExact(max, 1);       // throws ArithmeticException

Watch out

Computing a midpoint as (lo + hi) / 2 with large ints, which can overflow; use lo + (hi - lo) / 2.

Processes and threads

Also called operating system, OS, concurrency

What
The operating system runs each program as a process with its own memory. A process can have several threads that share that memory and run at the same time on different CPU cores.
Why
It explains why one crashed program does not take down others, how servers handle many requests, and why shared data between threads needs care.

Watch out

Two threads updating the same variable without a lock, which loses updates at random (a race condition).

05 路 How computers run your code5 / 10