Skip to content

Instantly share code, notes, and snippets.

@squito
Last active June 24, 2019 15:35
Show Gist options
  • Save squito/66daf60be5a6fa4415c3b880150d4e8c to your computer and use it in GitHub Desktop.
Save squito/66daf60be5a6fa4415c3b880150d4e8c to your computer and use it in GitHub Desktop.
Interrupts, joins, OOMs, and uncaught exception handlers

most of the time, I see this -- notice that the Joiner thread does not seem to get an interrupt

> java Test      
both threads started
Starting oomer
Starting joiner
got exception from thread Thread[OOM thread,5,main]
java.lang.OutOfMemoryError: Java heap space
	at Test$OOMer.run(Test.java:10)
	at java.lang.Thread.run(Thread.java:745)
about to interrupt Thread[Joiner thread,5,main]
Successfully joined

but every once in a while (1/10 or so?), I see this:

> java Test
both threads started, main done
Starting joiner
Starting oomer
got exception from thread Thread[Thread-0,5,main]
java.lang.OutOfMemoryError: Java heap space
	at Test$OOMer.run(Test.java:10)
	at java.lang.Thread.run(Thread.java:745)
about to interrupt Thread[Thread-1,5,main]
interrupted!
got exception from thread Thread[Thread-1,5,main]
java.lang.RuntimeException: java.lang.InterruptedException
	at Test$Joiner.run(Test.java:44)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.InterruptedException
	at java.lang.Object.wait(Native Method)
	at java.lang.Thread.join(Thread.java:1245)
	at java.lang.Thread.join(Thread.java:1319)
	at Test$Joiner.run(Test.java:40)
	... 1 more
about to interrupt Thread[Thread-1,5,main]

I'm testing with:

> java -version
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)

you can loop like so:

> for i in `seq 1 10`;
do 
  java Test
done

If I run with -XX:OnOutOfMemoryError="kill -9 %p", then it consistently dies like this (doesn't finish join or interrupt):

> java -XX:OnOutOfMemoryError="kill -9 %p" Test
Starting joiner
Starting oomer
both threads started
#
# java.lang.OutOfMemoryError: Java heap space
# -XX:OnOutOfMemoryError="kill -9 %p"
#   Executing "kill -9 45102"...
import java.util.ArrayList;
public class Test implements Runnable {
public static class OOMer implements Runnable {
public void run() {
System.out.println("Starting oomer");
ArrayList<byte[]> stuff = new ArrayList<>();
while (true) {
stuff.add(new byte[100000000]);
}
}
}
public static class ExceptionHandler implements Thread.UncaughtExceptionHandler {
final Thread interruptMe;
public ExceptionHandler(Thread interruptMe) {
this.interruptMe = interruptMe;
}
public void uncaughtException(Thread t, Throwable e) {
System.out.println("got exception from thread " + t);
e.printStackTrace();
System.out.println("about to interrupt " + interruptMe);
interruptMe.interrupt();
}
}
public static class Joiner implements Runnable {
final Thread joinOn;
public Joiner(Thread joinOn) {
this.joinOn = joinOn;
}
public void run() {
try {
System.out.println("Starting joiner");
joinOn.join();
System.out.println("Successfully joined");
} catch(InterruptedException e) {
System.out.println("interrupted!");
throw new RuntimeException(e);
}
}
}
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("interrupted");
}
System.out.println("alive");
}
}
public static void main(String[] args) {
Thread oomThread = new Thread(new OOMer(), "OOM thread");
Thread joinerThread = new Thread(new Joiner(oomThread), "Joiner thread");
ExceptionHandler eh = new ExceptionHandler(joinerThread);
Thread.setDefaultUncaughtExceptionHandler(eh);
joinerThread.start();
oomThread.start();
System.out.println("both threads started");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment