Backend Development 9 min read

Typical Java Crash Scenarios with Sample Code

This article examines typical Java application failure scenarios—including heap OOM, memory leaks, CPU spikes, thread leaks, deadlocks, stack overflows, and blocked threads—providing concise code examples and practical diagnostic tips for root cause analysis.

IT Services Circle
IT Services Circle
IT Services Circle
Typical Java Crash Scenarios with Sample Code

Java programs run on a garbage‑collected runtime and often allocate a large heap at startup; combined with JIT optimizations they can be as fast as native C++ code, but issues such as memory leaks or crashes can be harder to pinpoint without tools like JFR.

1. Heap Space Overflow (OOM)

An OutOfMemoryError is usually caused by a memory leak that makes GC pauses longer and heap usage keep rising. The following demo continuously inserts data into a HashMap that is a GC root, eventually exhausting the heap.

import java.util.HashMap;
public class OOMDemo {
    static HashMap
myMap = new HashMap<>();
    public static void start() throws Exception {
        while (true) {
            myMap.put("key" + counter, "Large string..." + counter);
            ++counter;
        }
    }
}

2. Memory Leak

Memory leaks are conceptually similar to OOM but refer to unexpected, sustained growth of heap usage. Tools such as jmap or pmap are often needed to locate the root cause. A common leak occurs when hashCode and equals are not overridden correctly.

// leak example : created by xjjdog 2022
import java.util.HashMap;
import java.util.Map;
public class HashMapLeakDemo {
    public static class Key {
        String title;
        public Key(String title) { this.title = title; }
    }
    public static void main(String[] args) {
        Map
map = new HashMap<>();
        map.put(new Key("1"), 1);
        map.put(new Key("2"), 2);
        map.put(new Key("3"), 2);
        Integer integer = map.get(new Key("2"));
        System.out.println(integer);
    }
}

3. CPU Spike

A tight infinite loop can fully consume CPU cores. The demo launches several threads that each run an endless loop.

public class CPUSpikeDemo {
    public static void start() {
        new CPUSpikerThread().start();
        new CPUSpikerThread().start();
        new CPUSpikerThread().start();
        new CPUSpikerThread().start();
        new CPUSpikerThread().start();
        new CPUSpikerThread().start();
        System.out.println("6 threads launched!");
    }
}
public class CPUSpikerThread extends Thread {
    @Override
    public void run() {
        while (true) {
            // Just looping infinitely
        }
    }
}

4. Thread Leak

Creating threads without ever terminating them quickly exhausts system resources. The following code continuously spawns new threads that sleep forever.

public class ThreadLeakDemo {
    public static void start() {
        while (true) {
            new ForeverThread().start();
        }
    }
}
public class ForeverThread extends Thread {
    @Override
    public void run() {
        // Put the thread to sleep forever, so they don't die.
        while (true) {
            try {
                Thread.sleep(10 * 60 * 1000);
            } catch (Exception e) {}
        }
    }
}

5. Deadlock

Deadlocks are rare but severe; they occur when two threads hold locks the other needs. The demo shows two synchronized methods calling each other, causing a circular wait.

public class DeadLockDemo {
    public static void start() {
        new ThreadA().start();
        new ThreadB().start();
    }
}
public class ThreadA extends Thread {
    @Override
    public void run() { CoolObject.method1(); }
}
public class ThreadB extends Thread {
    @Override
    public void run() { HotObject.method2(); }
}
public class CoolObject {
    public static synchronized void method1() {
        try { Thread.sleep(10 * 1000); } catch (Exception e) {}
        HotObject.method2();
    }
}
public class HotObject {
    public static synchronized void method2() {
        try { Thread.sleep(10 * 1000); } catch (Exception e) {}
        CoolObject.method1();
    }
}

6. Stack Overflow

A recursive call without a termination condition overflows the JVM stack. The demo simply calls start() recursively.

public class StackOverflowDemo {
    public void start() { start(); }
}

The stack size can be adjusted with the -Xss JVM option (e.g., -Xss128K ).

7. BLOCKED Thread

A thread in the BLOCKED state is waiting to acquire a lock, often because a request takes too long. The following example creates several threads that invoke a synchronized method which sleeps indefinitely, causing BLOCKED threads.

public class BlockedAppDemo {
    public static void start() {
        for (int i = 0; i < 10; ++i) {
            new AppThread().start();
        }
    }
}
public class AppThread extends Thread {
    @Override
    public void run() { AppObject.getSomething(); }
}
public class AppObject {
    public static synchronized void getSomething() {
        while (true) {
            try { Thread.sleep(10 * 60 * 1000); } catch (Exception e) {}
        }
    }
}

Frequent BLOCKED states indicate that the application is too slow; increasing the thread pool size (e.g., Tomcat's maxThreads) may help if CPU resources are still available.

End

The examples above cover the most common Java failure patterns; diagnosing them usually requires deep knowledge of the runtime and appropriate tooling such as jstack , fastthread, or custom monitoring utilities.

debuggingJavaThreadMemory Leakcrash
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.