相同进程,一个线程OOM,其余线程可以正常运行么?

有很多文章(有一个文章分别从栈,堆以及1.8之前的永久代,1.8之后的元数据区分别进行了阐述)对这个问题进行了阐述,首先可以确定的是 可以运行
当一个线程抛出OOM(Out Of Memory)异常之后会被停止,会立刻进行GC,内存空间释放,不影响其余的线程。
但是很多测试代码都是往一个线程内的集合存放String数据,所以,当线程停止的时候,这个线程里面的集合就会被清理掉,集合内部的东西自然也会被清理(无根可达)。

但是我们把集合放在全局变量里面呢?或者static修饰的全局变量呢?
对上面的两种情况分别进行了测试,答案依旧是***可以运行***。
按照常理来讲,static是根节点,基本上不会被GC掉的,所以为什么呢?

public class ThreadPoolStr {static List<String> list= new ArrayList();public static void main(String[] args) throws IOException {new Thread(()->{while (true){Thread.currentThread().setName("添加list");Random random = new Random();Integer i = random.nextInt(100);list.add(new String(i.toString()));}}).start();new Thread(()->{Thread.currentThread().setName("测试你好");while (true){try {Thread.sleep(1000);System.out.println("你好");} catch (InterruptedException e) {e.printStackTrace();}}}).start();new Thread(()->{Thread.currentThread().setName("测试list以及里面的内容有没有被GC");while (true){try {Thread.sleep(1000);System.out.println(list.size());System.out.println(list.get(0));} catch (InterruptedException e) {e.printStackTrace();}}}).start();}
}

上面几个线程的打印结果
当添加线程OOM之后
测试你好线程 依旧坚挺
测试list内容是否完整,是否被GC 打印结果时没有被GC。
显然我想不明白为啥了,为什么内存明明已经不够了,另外的线程却并没有收到影响?
是因为栈分配?
那我们试试往线程里面放一个大对象?让他不会往栈里面分配,往TLAB里面分配,直接往新生代丢甚至直接丢入old区?
(TLAB 线程本地分配 占用的也是Eden的内存 堆内存满了 显然这里也不能分配了)
于是我们设置写一个不可以栈内存分配的对象 让其余的线程操作(只要不是线程私有的,就不可以栈上分配,也不可以TLAB)

public class ThreadPoolStr {static List<String> list = new ArrayList();//sir是我自定义的一个类 显然这个是堆内存分配的static SIR sir = new SIR();public static void main(String[] args) throws IOException, InterruptedException {new Thread(() -> {while (true) {Thread.currentThread().setName("添加list");Random random = new Random();Integer i = random.nextInt(100);list.add(new String(i.toString()));}}).start();new Thread(() -> {Thread.currentThread().setName("测试你好");while (true) {try {Thread.sleep(1000);List<SIRResult> list = new ArrayList<>();list.add(new SIRResult());sir.setList(list);System.out.println(sir.toString());System.out.println("你好");} catch (InterruptedException e) {e.printStackTrace();}}}).start();new Thread(() -> {Thread.currentThread().setName("测试list以及里面的内容有没有被GC");while (true) {try {Thread.sleep(1000);System.out.println(list.size());System.out.println(list.get(0));} catch (InterruptedException e) {e.printStackTrace();}}}).start();Thread.sleep(5000);sir = new SIR();sir.setId("213123");System.out.println("sir"+sir.hashCode());}
}

上面的测试,依旧是不会受到影响。
为了防止我代码的问题 我有关闭了逃逸分析,标量替换什么的 绝对不会本地分配
-XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:-UseTLAB
结果依旧是 一个线程OOM 其余线程不会收到影响。
我又用测试你好线程测试了一下往list继续新增,增加一条都不行了,会OOM,再次说明list 没有被GC。
所以无论如何测试
最后的结果肯定是
同一个进程,单线程发生OOM,绝对不会影响到其余的线程。
但是为啥子 会出现我这次测试的情况,我不理解,还希望能人大佬们来解答。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部