服务遇到内存溢出,定位以及解决办法

之前遇到了本地服务运行正常,但是上了测试环境之后,就报出了内存溢出的异常,也就是OutOfMemoryError异常.
经过日志上的定位,找到代码大概的位置

业务逻辑是这样的:读取文件的内容,将每一行的内容,进行替换指定的内容。

public void testReplace(File file) {
	// ....		
    // 传过来的文件 File file进行处理,进行一些业务处理,之后拿到content
	List<PpBorderDetail> ppBorderDetailList = dpOrderRepository
				.findByOrderStatusAndBorderStatusAndConditionsWithStock(dpOrderNos, fromWsNo, false,
						DpSplitResultType.BIG_BORDER.getIndex(), DpSplitResultType.SMALL_PANEL_BORDER.getIndex(), true)
				.stream().map(this::genBorderStkOutDetail)
				.collect(Collectors.groupingBy(detail -> detail.getDpOrderNo()
						+ "_" + detail.getDpBorderItemNo() + "_" + detail.getCalcuLength()))
				.entrySet().stream().map(this::genBorderStkOutDetail)
				.sorted(Comparator.comparing(PpBorderDetail::getDpTypeName)
						.thenComparing(PpBorderDetail::getDpBorderItemName)
						.thenComparing(PpBorderDetail::getDeliveryDate).thenComparing(PpBorderDetail::getDpOrderNo))
				.collect(Collectors.toList());
	  
	// 对文件里的文本内容进行对应的替换
	String s;
	// 模拟大概的情况
	for(PpBorderDetail ppBorderDetail : ppBorderDetailList) {
		for (String str: ppBorderDetail.getContent()) {
			s = str.replace("\r", "\r\n");
			// 后续对s进行了相关的操作
		}
	}
}

乍看之下,没毛病,传过来的是File文件,然后对文件里面的内容进行处理。跟测试沟通之后才发现,传过来的是一个大文件。我在想,如果一个大文件,要处理的文本内容,里面有几万行,甚至几十万行,这些处理应该是没问题的。
服务器性能好,对这些压力扛得住,但是怎么就报出了OutOfMemoryError异常了呢?根据查阅一些资料,大量的String的处理,产生了大量的对象,JVM来不及回收,就会报出这种异常了。于是乎,对上面的代码进行了一些改动。

public void testReplace(File file) {
	// ....		
    // 传过来的文件 File file进行处理,进行一些业务处理,之后拿到content
	List<PpBorderDetail> ppBorderDetailList = dpOrderRepository
				.findByOrderStatusAndBorderStatusAndConditionsWithStock(dpOrderNos, fromWsNo, false,
						DpSplitResultType.BIG_BORDER.getIndex(), DpSplitResultType.SMALL_PANEL_BORDER.getIndex(), true)
				.stream().map(this::genBorderStkOutDetail)
				.collect(Collectors.groupingBy(detail -> detail.getDpOrderNo()
						+ "_" + detail.getDpBorderItemNo() + "_" + detail.getCalcuLength()))
				.entrySet().stream().map(this::genBorderStkOutDetail)
				.sorted(Comparator.comparing(PpBorderDetail::getDpTypeName)
						.thenComparing(PpBorderDetail::getDpBorderItemName)
						.thenComparing(PpBorderDetail::getDeliveryDate).thenComparing(PpBorderDetail::getDpOrderNo))
				.collect(Collectors.toList());
	  
	// 对文件里的文本内容进行对应的替换
	String s;
	// 模拟大概的情况
	for(PpBorderDetail ppBorderDetail : ppBorderDetailList) {
		for (String str: ppBorderDetail.getContent()) {
			if (str.startsWith("\r")) {
                s = str.replace("\r", "\r\n");
                // 后续对s进行了相关的操作
            }
		}
	}
}

增加了相关的逻辑判断,这样不用每次都进行处理,产生临时对象,这是我猜想的。验证的话,还是等发布测试环境之后才能知道最后的结果,果然,测试大文件的内容,没有报错内存溢出的问题了。
这是一次工作经验之谈,看过网上其他的解决办法,大部分都是调JVM参数什么的,我想,还是根据个人的实际工作来谈吧,并不是每次都要照着别人的来做,可以学习别人的,借鉴别人的,但具体问题还是根据自己的实际情况来定的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

exodus3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值