1. The Hook (The "Byte-Sized" Intro)
- In a Nutshell: Object creation = 4 steps: (1) Class loading, (2) Memory allocation, (3) Initialization, (4) Reference assignment.
- Allocation: Starts in Eden space (Young Gen). TLAB (Thread-Local Allocation Buffer) = fast, lock-free allocation per thread.
- Object layout: Header (mark word + class pointer) + instance data + padding.
- String pool: Interned strings (literals) in heap, shared, memory-efficient. intern() adds to pool.
- Key: Objects start young, promoted if survive!
Think of factory production line. Eden = assembly area (new products). TLAB = worker's personal workstation (no waiting for shared tools). String pool = parts warehouse (reuse common parts, don't duplicate). Object header = product barcode (metadata)!
2. Conceptual Clarity (The "Simple" Tier)
💡 The Analogy
- Eden Space: Nursery (newborns arrive here)
- TLAB: Personal baby crib (per-thread, no sharing)
- String Pool: Library (borrow books, don't buy duplicates)
3. Technical Mastery (The "Deep Dive")
Object Creation Steps
| Step | Action | Location |
|---|---|---|
| 1. Class Loading | Load class if not loaded | Metaspace |
| 2. Memory Allocation | Allocate space | Eden (TLAB) |
| 3. Initialization | Set default values | Heap |
| 4. Constructor | Run constructor | Heap |
| 5. Reference Assignment | Assign to variable | Stack (reference) |
4. Interactive & Applied Code
java
public class ObjectCreationDemo {
public static void main(String[] args) {
demonstrateCreation();
demonstrateStringPool();
demonstrateTLAB();
}
// Object creation process
static void demonstrateCreation() {
System.out.println("=== OBJECT CREATION ===");
// Step 1: Class loading (if not already loaded)
// Step 2: Memory allocation in Eden (via TLAB)
// Step 3: Default initialization (name=null)
// Step 4: Constructor runs
Person p = new Person("Alice");
// Reference 'p' on stack, object in Eden (heap)
System.out.println(p.name);
}
// String pool demonstration
static void demonstrateStringPool() {
System.out.println("\n=== STRING POOL ===");
// String literals → String pool
String s1 = "Hello"; // Created in pool
String s2 = "Hello"; // Reuses s1 (same object!)
System.out.println("s1 == s2: " + (s1 == s2)); // true (same reference)
// new String() → Regular heap
String s3 = new String("Hello"); // New object in heap
System.out.println("s1 == s3: " + (s1 == s3)); // false (different objects)
// intern() → Add to pool
String s4 = s3.intern(); // Returns pool reference
System.out.println("s1 == s4: " + (s1 == s4)); // true (pool reference)
// Memory savings
String[] messages = new String[1000];
for (int i = 0; i < 1000; i++) {
messages[i] = "Message"; // ✅ All share same pool object!
}
// Only 1 "Message" object vs 1000 if using new String()
}
// TLAB demonstration (conceptual)
static void demonstrateTLAB() {
System.out.println("\n=== TLAB (Thread-Local Allocation Buffer) ===");
// Multiple threads allocating objects
Runnable task = () -> {
// Each thread has its own TLAB
for (int i = 0; i < 1000; i++) {
Object obj = new Object(); // Fast, lock-free (TLAB)
}
System.out.println(Thread.currentThread().getName() + " done");
};
// Threads allocate in parallel without contention
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
}
}
class Person {
String name;
Person(String name) {
this.name = name;
}
}
// Object memory layout (conceptual)
class ObjectLayoutDemo {
public static void main(String[] args) {
/*
Object layout in memory:
+-------------------+
| Object Header | 12-16 bytes
| - Mark Word | 8 bytes (hash, age, lock)
| - Class Pointer | 4-8 bytes (compressed oops)
+-------------------+
| Instance Data | Variable size
| - Fields |
+-------------------+
| Padding | Align to 8 bytes
+-------------------+
*/
Person p = new Person("Alice");
// Rough memory calculation:
// Header: 12 bytes
// name reference: 4 bytes (compressed)
// Padding: 0 bytes (12+4=16, already aligned)
// Total: ~16 bytes (object itself)
// + String object memory
}
}
// String concatenation
class StringConcatenationDemo {
public static void main(String[] args) {
// ❌ BAD: Creates many intermediate String objects
String result = "";
for (int i = 0; i < 1000; i++) {
result += i; // Each iteration creates new String!
}
// ✅ GOOD: StringBuilder (single mutable object)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i); // Modifies same object
}
String result2 = sb.toString();
}
}5. The Comparison & Decision Layer
| String Literal | new String() | Use When |
|---|---|---|
| String pool | Regular heap | Literals (pool) |
| Shared | Unique | Need unique (heap) |
| Memory-efficient | Memory wasteful | Usually literals |
6. The "Interview Corner" (The Edge)
The "Killer" Interview Question: "How many objects are created?"
java
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");Answer: 2 objects!
- 1 object: "Hello" in String pool (shared by s1 and s2)
- 1 object: new String() in regular heap (s3)
java
s1 == s2 // true (same pool object)
s1 == s3 // false (s3 is different heap object)
s1.equals(s3) // true (same content)Pro-Tips:
- TLAB benefits:
text
Without TLAB:
- All threads compete for Eden space
- Synchronization overhead
- Slower allocation
With TLAB:
- Each thread has private buffer (~1% of Eden)
- Lock-free allocation
- Fast path
- Falls back to slow path if TLAB full- String pool memory:
java
// ✅ GOOD: Pool (memory efficient)
String s1 = "Hello";
String s2 = "Hello"; // Reuses s1
// ❌ BAD: Heap (memory wasteful)
String s3 = new String("Hello"); // Separate object
// Use new String() only when you need distinct object!