本文介绍: 最近客户反馈生产环境导入操作遇到任务一直执行中,并且入库的数据量一直不改变。java.lang.OutOfMemoryError: Java heap space (JVM 堆空间溢出)简单来说就是创建新的对象时, 堆内存中的空间不足以存放创建对象,导致此种问题的发生。

问题场景

最近客户反馈生产环境导入操作遇到任务一直执行中,并且入库的数据量一直不改变。通过日志查询,终于定位报错信息如下

java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Unknown Source) ~[na:1.8.0_221]
	at java.io.ByteArrayOutputStream.grow(Unknown Source) ~[na:1.8.0_221]
	at java.io.ByteArrayOutputStream.ensureCapacity(Unknown Source) ~[na:1.8.0_221]
	at java.io.ByteArrayOutputStream.write(Unknown Source) ~[na:1.8.0_221]
	at com.cxstar.common.utils.DESUtil.decryptFile(DESUtil.java:193) ~[cxstar-common-1.0.0.jar!/:1.0.0]
	at com.cxstar.business.service.impl.ArchiveServiceImpl.upload(ArchiveServiceImpl.java:103) ~[cxstar-business-1.0.0.jar!/:1.0.0]
	at com.cxstar.business.factory.AsyncFactory.importAttachment(AsyncFactory.java:1016) ~[cxstar-business-1.0.0.jar!/:1.0.0]
	at com.cxstar.business.factory.AsyncFactory.access$800(AsyncFactory.java:62) ~[cxstar-business-1.0.0.jar!/:1.0.0]
	at com.cxstar.business.factory.AsyncFactory$7.run(AsyncFactory.java:708) ~[cxstar-business-1.0.0.jar!/:1.0.0]
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:1.8.0_221]
	at java.util.concurrent.FutureTask.run(Unknown Source) ~[na:1.8.0_221]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) ~[na:1.8.0_221]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:1.8.0_221]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_221]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_221]
	at java.lang.Thread.run(Unknown Source) [na:1.8.0_221]

问题分析解决

java.lang.OutOfMemoryError: Java heap space (JVM 堆空间溢出)简单来说就是创建新的对象时, 堆内存中的空间不足以存放创建对象,导致此种问题的发生。

1.优化项目代码

根据报错信息定位内存消耗较大的代码然后对其进行重构或者优化算法。如果是在生产环境,务必要在内存消耗过大的代码出增加日志信息输出,否则容易像我定位一晚上才找到问题所在
在这里插入图片描述

2.提升Java heap size

增加堆内存空间设置,此种方式容易操作可以较快解决当前问题,但是总体来说还是需要找到项目代码中的问题才是最优解,毕竟内存总是有限

客户生产环境服务器是8g内存,并且操作系统比较老的windows server 2008服务器。在部署项目时使用winsw工具将jar安装服务。因此在项目启动时,增加内存参数修改配置如下:

<service&gt;
    <id&gt;app-id</id&gt;
    <name&gt;app-name service</name&gt;
    <description&gt;application descriptions</description>

	<!-- 配置启动使用jar -jar方式运行项目 -->
    <executable>java</executable>
    <arguments>-jar -server -Xms4096m -Xmx4096m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m  "D:applicationapi-rest-1.0.0.jar"</arguments>

    <startmode>Automatic</startmode>
    <logpath>%BASE%logs</logpath>
    <logmode>rotate</logmode>
</service>

3.JVM参数配置

配置参考

服务器内存8G ,所以可以采取以下配置
set JAVA_OPTS=-server -Xms4096m -Xmx4096m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m

服务器内存4G ,所以可以采取以下配置
set JAVA_OPTS=-server -Xms2048m -Xmx2048m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m

服务器内存2G ,所以可以采取以下配置
set JAVA_OPTS=-server -Xms1024m -Xmx1024m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m

服务器内存1G ,所以可以采取以下配置
set JAVA_OPTS=-server -Xms512m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=256M -XX:MaxPermSize=256m

服务器内存512M ,所以可以采取以下配置
set JAVA_OPTS=-server -Xms256m -Xmx256m -XX:PermSize=256M -XX:MaxNewSize=128m -XX:MaxPermSize=128m

堆区参数配置说明

堆区:通过new方式创建对象(一个类的实例)、数组所占的空间。所有的线程共享区域
堆区还细分为新生代(Eden空间、From Survivor空间、To Survivor空间)、老年代(Tenured Generation空间)

参数 含义
-Xms java虚拟机初始化时的最小内存
-Xmx java虚拟机使用最大内存

通常会将-Xms 与-Xmx两个参数的配置相同的值,其目的是为了能够在java垃圾回收机制清理堆区后不需要重新分隔计算堆区大小浪费资源

参数名 含义
-XX:newSize 表示对象创建初始内存的大小,应小于-Xms的值
-XX:MaxnewSize 表示对象创建可被分配的内存的最大上限,应小于-Xmx的值
-Xmn jdk1.4后对-XX:newSize、-XX:MaxnewSize两个参数同时进行配置

堆区参数配置说明

堆区:代码、常量外部访问(比如流在传输数据时所占用资源)等,java垃圾回收机制作用堆区,非堆区不会被java垃圾回收机制进行处理

参数名 含义
-XX:PermSize 表示非堆区初始内存分配大小方法区)
-XX:MaxPermSize 表示对非堆区分配的内存的最大上限(方法区)

在配置之前一定要慎重的考虑一下自身软件需要的非堆区内存大小,因为此处内存是不会被java垃圾回收机制进行处理的地方。并且更加要注意的是最大堆内存与最大非堆内存的和绝对能够超出操作系统可用内存。

原文地址:https://blog.csdn.net/qq_29864051/article/details/130962792

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_46158.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注