我有一个 Java/Java EE Web 应用程序。
通常,当我看到应用程序由于高堆使用率(或内存不足的情况)而停止响应时,我还会看到线程被阻塞(通过线程转储) - 通常在日志记录和随机事件上。
我在 Web 应用程序中不止一次看到过这种情况。
内存不足的情况和阻塞的线程之间是否有任何关联?
我有一个 Java/Java EE Web 应用程序。
通常,当我看到应用程序由于高堆使用率(或内存不足的情况)而停止响应时,我还会看到线程被阻塞(通过线程转储) - 通常在日志记录和随机事件上。
我在 Web 应用程序中不止一次看到过这种情况。
内存不足的情况和阻塞的线程之间是否有任何关联?
是的,OOM 和阻塞线程之间存在直接关联。这是由于线程试图在堆上分配内存而无法获得足够内存的原因。大多数情况下,您会在日志记录、类加载、资源查找、IO 周围看到阻塞的线程。这些都是需要新内存分配的情况。
是的,因为线程是你的代码执行的地方,你的代码需要内存。Java 是面向对象的,因此创建新对象是极其常见的事情。当 JVM 出现内存问题时,会尝试分配更多内存块,直到可以授予内存为止。
与外部系统 (I/O) 的接口是常见的线程阻塞点,因为这些通常涉及大块的内存分配(例如用于格式化的字符串缓冲区、由类加载器读取 .class 文件、为数据库结果集)。
这是排除 OutOfMemoryError 非常困难的众多原因之一。当您的堆空间不足/耗尽时,每件事都会减慢并中断,以使将症状与原因区分开来变得困难。
是的,存在相关性。虽然线程共享堆,但它们有自己的堆栈。两者都是从可用内存中分配的内存。正如您在案例记录中提到的那样,一个线程可能正在做一些工作。对于日志记录线程可能会在内存中保存一些日志,并将尝试将它们放入日志文件中。由于存在不同的日志记录线程,因此它们将等待轮流访问日志文件。如果线程等待文件的时间过长,那么它们会将日志数据长时间保存在内存中。如果这种情况继续发生,那么内存中会有太多线程和太多数据。最终,当有人试图获取内存并且没有可用的内存时,JVM 会遇到内存不足的情况。