说明:记一次内存溢出的情况,标题是主要报错信息,具体的报错信息如下:
出现这个情况我首先去查看了服务进程,发现服务进程直接被自动杀掉,然后看了报错信息知道跟内存有关,就用free -h查看了服务器内存,发现剩余空间充足,我先去百度了一下查看了一些解决方法,比如修改vm.overcommit_memory的值去改变内存分配策略
vm.overcommit_memory配置
linux系统会对大部分的申请都回复yes,以便于运行更多的程序。但是有些程序申请完内存后并不一定会立马使用,这就叫做overcommit。
而通过vm.overcommit_memory的配置就可以控制overcommit的内存分配策略,主要分为以下三种:
0:内核首先会检查是否有足够的内存分配,如果没有就反馈申请失败,也就是cannot allocate memory的出现
1:内核允许超量使用内存直到内存用完为止
2:表示内核绝不允许超量使用内存,即系统的内存空间不能超过swap+50%的RAM值,50%是overcommit_ratio的默认值,该参数支持修改
但是因为前两天服务都是好好的,这种配置的情况不太可能,所以就定位到代码上,我自己写的模块很清楚没有这种大量循环的情况,所以重点查看了下同事写的功能模块,最终发现了一个死循环:
String startTimeStr = "2330";
String endTimeStr = "2345";
LocalTime startTime = LocalTime.parse(startTimeStr, DateTimeFormatter.ofPattern("HHmm"));
LocalTime endTime = LocalTime.parse(endTimeStr, DateTimeFormatter.ofPattern("HHmm"));
List<String> timePoints = new ArrayList<>();
LocalTime currentTime = startTime;
while (currentTime.isBefore(endTime) || currentTime.equals(endTime)) {
timePoints.add(currentTime.format(DateTimeFormatter.ofPattern("HHmm")));
currentTime = currentTime.plusMinutes(15);
}
这里我挑处的是有问题的循环,plusMinutes这个方法加分钟,但是如果是加到24:00,它是默认为00:00,所以造成了死循环,然后造成了内存溢出,服务进程直接被杀死。
另外这里说下我未去检查代码时为了不影响服务其他功能正常运行,我重新发布了服务,并在发布命令上加上内存限制的参数:
具体命令如下:
nohup java -jar -Duser.timezone=Asia/Shanghai -Xms512M -Xmx512M -XX:PermSize=512M -XX:MaxPermSize=1024M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC jar包名字 >> nohup.out &