Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this small Java program make MacOS restart?

Code is as follows

Set<Thread> threads = new HashSet<>();  Runnable r = () -> {     try {         Thread.sleep(Long.MAX_VALUE);     } catch (InterruptedException e) {         e.printStackTrace();     } };  for (int i = 0; i < 20000; i++) {     Thread t = new Thread(r);     threads.add(t);     t.start();     if (i % 100 == 0) {         System.out.println(i);     }     Thread.sleep(2); } 

When executed, I start seeing values like

0 100 200 300 

as expected, and it goes until I see:

3900 4000 Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread     at java.lang.Thread.start0(Native Method)     at java.lang.Thread.start(Thread.java:717)     at App.main(scratch.java:24) Java HotSpot(TM) 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGINT to handler- the VM may need to be forcibly terminated 

But then after a short while (10 - 20 seconds or so) MacOS decides to restart. What is the cause for the restart I am seeing here? The main thread throwing an exception, but the process having ~4000 threads sleeping causes ... what in the operating system? Is this a memory overflow or related to task scheduler of the OS?

 MacOS version: 10.14.3 (18D109) java version "1.8.0_202" Java(TM) SE Runtime Environment (build 1.8.0_202-b08) Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode) 
like image 767
Koray Tugay Avatar asked Feb 16 '19 14:02

Koray Tugay


People also ask

How do you restart a Java program by itself?

Strictly speaking, a Java program cannot restart itself since to do so it must kill the JVM in which it is running and then start it again, but once the JVM is no longer running (killed) then no action can be taken.


2 Answers

Despite the fact that the console shows the program has finished, the JVM process still runs until all resources are released. Meanwhile, your OS is out of threads, slow and unstable, which cause lagging in all processes, including the JVM finalization. As a self defense, the OS triggers a kernel panic. And that is why your MacOS restarts.

*OS - Operating System

like image 59
Badaro Avatar answered Oct 11 '22 11:10

Badaro


Java was built in the 90's, when there were only multi-core processors.

Surely Java has evolved, as have modern-day processors. Nowadays we have 8-core processors, with large caches (e.g: 12MB).

Even though concurrent processing has evolved much, Java is still designed around the 1-core processor model. But, enough with history, let me explain very very simply what happens.

Just by simply creating a new thread in Java, we waste a lot of memory.

Every thread consumes around ~ 512KB - 1MB, depending on your JVM version (see how much memory a thread takes in java and Java Thread: Retained Memory). Bearing this in mind, when continuously creating new Threads, at some point they will consume all of the heap's memory.

Now, I have never tried this on my own, but I assume that your computer's operating system shuts down/restarts due to the "out of memory" error, as a countermeasure. (This is much like the triple fault, that caused the infamous "Blue Screen of Death" on Windows, where the machine needed to restart to reset the CPU's state)

One possible solution for this, is to manually set the maximum heap size to be used by the JVM. Thus, when your program completely utilises the pre-allocated heap, it will not cause a shutdown. Please refer to this SO question on how to do this.

like image 40
Soutzikevich Avatar answered Oct 11 '22 11:10

Soutzikevich