专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 学习攻略 Java学习 Java内存溢出的原因

Java内存溢出的原因

更新时间:2022-04-21 10:59:24 来源:动力节点 浏览779次

JVM创建者在设计它时考虑了自动内存管理,这意味着程序员不需要担心内存分配和内存。未使用的对象可以以透明的方式自动释放,这非常方便,尤其是当您刚接触JVM时。但是,即使是一般情况下,要编写的代码也比传统方法少,而且不容易出错,因为传统方法要求您手动执行所有操作。

然而,实际情况并不像听起来那么理想,尤其是当你在开发具有巨大流量的长寿命应用程序时。虽然在JVM中引起内存泄漏比在C中更难,但仍然有可能。选择GC算法并将其参数化对性能也有很大的影响。而且,与任何抽象或自动化一样,如果您希望有意识地编写代码(这是专业的方法),您需要了解在幕后进行了哪些工作,以便能够预防或诊断问题。让我们来看看一些有用的工具和技术,这些工具和技术将帮助您找到应用程序崩溃或减速的原因,而不是快速工作并能够完成创建它的目的。

OutOfMemoryError

我们需要的第一件事是一段导致OutOfMemoryError的可靠代码。OutOfMemoryError是JVM引发的异常,它通知我们内存不足。可能有许多可能的原因导致抛出此异常,您可以查看异常的原因以了解发生了什么。现在,让我们编写一个应用程序,它会不断地分配内存,直到超过内存限制为止;

// file Application.scala
object Application {
  def main(args: Array[String]): Unit = {
    LazyList.from(0).toList
  }
}

编译一下:

scalac Application.scala

设置堆大小:

scala Application -J-Xmx10m -J-Xms10m

Xms和Xmx是JVM标志,指定应用程序的堆大小(或者简单地说,应用程序将拥有多少内存),其中Xms代表堆的初始大小,Xmx代表最大大小。

在我们的例子中,10MB是一个足够小的值,可以很快体验到内存不足。我们可以看到应用程序崩溃,错误如下:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

内存泄露的原因

在这种情况下,问题很明显。我们只有一个Java线程和一行代码。当然,实际应用程序要比这复杂得多。当我们在生产中看到OutOfMemoryError时,查看堆栈跟踪对我们没有帮助,因为导致问题的行是相当随机的,我们正在寻找一个分配内存且不释放内存的代码。我们可以在JVM内部查找问题的根源。

让我们添加一个-XX:+HeapDumpOnOutOfMemoryError标志,它将导致在OutOfMemoryError时生成堆转储。

scala Application -J-Xmx10m -J-Xms10m -J-XX:+HeapDumpOnOutOfMemoryError

我们可以看到,当我们的应用程序崩溃时,生成了一个扩展名为.hprof和PID的文件。这个文件是二进制的,所以我们需要一些工具来查看里面的内容。有很多工具可以完成这项工作,即使是在线的——比如HeapHero(http://heaphero.io/),如果数据不敏感,则可以使用。

导入文件后,您可以检查的最有用的内容是所有已分配对象的列表及其使用的内存百分比。我们可以从scala.collection.immutable不可变以及几乎构成整个堆的整数。这与我们在项目中所做的是一致的。列表和整数是显而易见的,因为我们创建List[int]作为结果。缺点. 这是因为Scala的LazyList使用了memorization,所以它保留了对所有元素的引用。

在磁盘空间明显受限的环境中(例如在云中),使用-XX:+HeapDumpOnOutOfMemoryError选项时要小心。这是一个完整的堆转储,这意味着在OutOfMemoryError的情况下,它至少与最大堆大小一样大。对于大的堆,这可能比分配给映像的磁盘空间大得多(因为您可能不需要太多空间,因为最好不要从服务直接写入磁盘)。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>