栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

JVM是否可以从OutOfMemoryError中恢复而无需重新启动

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JVM是否可以从OutOfMemoryError中恢复而无需重新启动

它可能有效,但是通常是一个坏主意。无法保证你的应用程序将成功恢复,或者无法知道它是否成功。例如:

  • 即使采取恢复步骤(例如释放保留的内存块)后,实际上可能没有足够的内存来执行请求的任务。在这种情况下,你的应用程序可能会陷入循环,在该循环中,它似乎反复出现恢复,然后再次耗尽内存。

  • OOME可以在任何线程上抛出。如果应用程序线程或库未设计为应对该问题,则可能会使某些长期存在的数据结构处于不完整或不一致的状态。

  • 如果线程由于OOME而死,则作为OOME恢复的一部分,应用程序可能需要重新启动线程。至少,这会使应用程序更加复杂。

  • 假设一个线程使用通知/等待或某种更高级别的机制与其他线程同步。如果该线程从OOME中退出,则可能会留下其他线程来等待通知(etc),这些消息永远不会出现…例如。为此进行设计可能会使应用程序更加复杂。

总而言之,设计,实施和测试要从OOME中恢复的应用程序可能会很困难,尤其是在应用程序(或其运行所在的框架或所使用的任何库)是多线程的情况下。将OOME视为致命错误是一个更好的主意。

另请参阅我对相关问题的回答:

编辑 -针对此后续问题:

换句话说,如果将OOME抛出到应用程序服务器(jboss / websphere / ..)中,我是否必须重新启动它?

不,你不必须重新启动。但这可能是明智的,特别是如果你没有良好/自动的方法来检查服务是否正常运行时。

JVM将恢复正常。但是,应用程序服务器和应用程序本身可能会恢复,也可能无法恢复,这取决于它们为应对这种情况而设计的程度。(我的经验是,某些应用程序服务器并非旨在解决此问题,并且设计和实施复杂的应用程序以从OOME中恢复非常困难,而正确测试它甚至更加困难。)

编辑2

针对此评论:

“其他线程可能会等待通知(等)永远不会到来”真的吗?被杀死的线程是否不会解开其堆栈,随即释放资源,包括持有的锁?

对真的!考虑一下:

线程#1运行此命令:

    synchronized(lock) {         while (!someCondition) {  lock.wait();         }    }    // ...

线程#2运行此命令:

    synchronized(lock) {         // do stuff         lock.notify();    }

如果线程#1正在等待通知,并且线程#2在该

// do something
部分中获得OOME ,则线程#2将不会进行
notify()
调用,线程#1可能会永远卡住,等待永远不会发生的通知。当然,可以保证线程
#2
释放
lock
对象上的互斥体…但这还不够!

如果不是,则线程运行的代码不是异常安全的,这是一个更普遍的问题。

我听说过“异常安全”这个词(尽管我知道你的意思)。Java程序通常不设计为可应对意外异常。确实,在上述情况下,使应用程序异常安全很可能介于困难与不可能之间。

你需要某种机制将线程#1的故障(由于OOME)变成对线程#2的线程间通信失败通知。Erlang可以做到这一点……但是Java却没有。他们之所以能够在Erlang中执行此操作,是因为Erlang进程使用严格的类似CSP的原语进行通信。即没有共享的数据结构!

(请注意,几乎所有意外的异常都可能导致上述问题……而不仅仅是Error异常。在某些类型的Java代码中,尝试从意外的异常中恢复可能会严重失败。)



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/441931.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号