我今天早上用Java测试了一些东西,我运行了这段代码,期待aN OutOfMemoryError
:
public class SynchronizedSpammer {
public static void main(String[] args) {
while (true) {
new Thread(new Runnable() {
public void run() {
syncWait();
}
}).start();
}
}
public static synchronized void syncWait() {
try {
Thread.sleep(100000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
令我惊讶的是,我的计算机耗尽了所有内存和交换后几秒钟就崩溃了。
这也有效:
public class Crash {
public static void main(String[] args) {
while (true) {
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
发生了什么事?为什么内存不受Xmx的限制?
答案 0 :(得分:3)
您创建了太多Thread
个对象!
while (true) {
new Thread(new Runnable() {
public void run() {
syncWait();
}
}).start();
}
你是说这个吗?
new Thread(new Runnable() {
public void run() {
while (true) {
syncWait();
}
}
}).start();
答案 1 :(得分:1)
在用完堆栈空间之前,你的堆空间会用完。
这里的问题是你正在创建和启动很多线程。所有线程都在syncWait()
调用时阻塞,但直到它们到达那里,线程调度程序才忙于上下文切换。除了无限while
循环之外,还会重载CPU。
这不是一个记忆问题,尽管它会如何结束。
这里有一些相关的阅读:
答案 2 :(得分:0)
StackOverflowError
将被抛出。
你的线程没有做太多,所以他们没有填满他们的筹码,所以你没有得到StackOverflowError
。你的内存不足,因为你创建的线程太多而且每个线程都占用了一些内存(它需要内存用于它的堆栈)。
如果你真的想得到StackOverflowError
你可以做的是设置-Xss 104k(104千字节堆栈大小)和:
public class StackEater{
public static void main(String[] args) throws Exception {
Thread t = new Thread(new Runnable() {
public void run() {
printLevel(1);
}});
t.start();
t.join()
}
public static void printLevel(long n) {
System.out.println(n);
printLevel(n+1);
}
}
将最大数字与:
进行比较public class StackEater{
public static void main(String[] args) throws Exception {
Thread t = new Thread(new Runnable() {
public void run() {
printLevel(1, 1);
}});
t.start();
t.join()
}
public static void printLevel(long n, long m) {
System.out.println(n);
printLevel(n+1, m+1);
}
}
你会看到第二个例子会在抛出异常之前打印出较小的n,因为它通过引入额外的参数来使用更多的堆栈空间。