最近将写好的一个需要从磁盘往内存中读取大量数据的一个项目准备部署到 linux 上,但在 linux 中启动项目时,项目可以启动成功,但是通过请求访问项目的时候,会报 java.lang.OutOfMemoryError Java heap space 的错误,导致整个项目不能正常运行。
java.lang.OutOfMemoryError Java heap space 表示 Java 的堆内存溢出。
每个 Java 程序都只能使用一定量的内存,这种限制是由于 JVM 的启动参数决定的。并且 Java 程序的内存分为两部分:
这两个区域的最大内存大小是由 JVM 启动参数 -Xmx 和 -XX:MaxPermSize 指定,如果没有指定,则会根据操作系统版本、JVM 版本和物理内存的大小来确定。
当创建新的对象时,堆内存中的空间不足以存放新创建的对象,就会引入 java.lang.OutOfMemoryError Java heap space 错误,并且只要超过了堆内存的最大限度,就会报错,和物理内存没有直接关系。
数据量超过堆内存的最大限度: 当往堆内存中增加的数据量超过了最大限度,则会报 java.lang.OutOfMemoryError Java heap space。
超出预期的访问量/数据量: 应用系统设计时,一般是有容量定义的,当访问量或者数据量突然飙升,超过预期的阈值,那么在峰值所在的时间段,程序就可能会卡死,并触发 java.lang.OutOfMemoryError Java heap space。
内存泄露: 由于代码中的某些错误,导致系统占用的内存越来越多,如果某段代码存在内存泄露(即逻辑上不再使用,但没有呗垃圾收集器给干掉的对象),那么每次执行它时就会出现更多的垃圾对象,占用更多的内存。当泄露的对象耗光了堆中的内存,则会报 java.lang.OutOfMemoryError Java heap space。
对于内存泄露等增加对内存不能解决的问题,要从代码上去根本解决。
对于设置的内存不足满足程序正常运行,只需要增大堆内存就行。
JVM 参数介绍:
| 参数 | 说明 |
|---|---|
-Xms | 指定 JVM 的初始内存大小。建议和 -Xmx 大小一样,防止因为内存收缩或突然增大带来的性能影响。 |
-Xmx | 指定JVM 的最大内存大小。建议为物理内存的80%。 |
-Xmn | 指定 JVM 中 New Generation(堆空间的新生代空间)的大小。这个参数很影响性能,如果你的程序需要比较多的临时内存,建议设置到512M,如果用的少,尽量降低这个数值,一般来说128或256足以使用了。 |
-XX:PermSize | 指定 JVM 中 Perm Generation(永久存储区)的最小值。这个参数需要看你的实际情况。可以通过 jmap 命令看看到底需要多少。 |
-XX:MaxPermSize | 指定 Perm Generation 的最大值。 |
-Xss | 指定线程桟大小。一般来说,webx 框架下的应用需要256K。 如果程序中有大规模的递归行为,请考虑设置到512K或1M。这个参数对性能的影响比较大的,在相同物理内存下,减小这个值能生成更多的线程。 |
由于该项目涉及到了请求访问时,每次请求都会从文件中读取大量的数据,因此初步判断报错原因是堆内存不够。
由于该项目是一个 springboot 项目,内置了 tomcat,则直接通过以下方式去修改并启动项目即可:
nohup java -Xms1024m -Xmx1024m -Xss1024K -XX:PermSize=128m -XX:MaxPermSize=256m -jar xxxx.jar > /dev/null 2>&1 &
通过修改了堆内存的值之后,该项目就能成功的运行并且访问了!
通过 jmap -heap pid 命令,来查询该项目的内存使用情况,可以发现内存占用率并未到达预设的值。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MABvGSxJ-1662650504780)(C:/Users/bbbbbge/Pictures/接单/1662650453534.png)]](https://1000bd.com/contentImg/2023/11/05/133027053.png)