导出数据,数据量太大,一直处于加载中,然后刷新页面,也刷新不出来。
原因:
1、在反序列化 Redis 数据时发生了问题,导致 Java 虚拟机耗费过多时间在垃圾回收上,最终触发了 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误。这可能是由于 Redis 存储的某些数据过大或者存储了大量的数据,导致在反序列化时内存使用过多,垃圾回收器无法及时清理。
2、java.lang.OutOfMemoryError: Java heap space 错误表示 JVM 的堆空间不足,无法满足程序运行的需求。这通常发生在应用程序试图分配更多内存而堆的可用空间已经耗尽的情况下。
程序试图使用更多的内存,但是系统当前可用的内存空间不足。这可能是由于系统负载较大或者应用程序需要处理大量数据导致的
解决措施
对于原因1,可以调整垃圾回收设置:
使用并发垃圾收集器(Concurrent Garbage Collector)可以帮助减小垃圾回收对应用程序的影响,提高应用程序的性能。在Java虚拟机的启动参数中添加 -XX:+UseG1GC
参数来启用G1垃圾收集器。
修改启动脚本,将Java虚拟机的启动命令中添加 -XX:+UseG1GC
参数。例如:
java -Xms2G -Xmx3G -XX:+UseG1GC -jar your-application.jar
对于原因2:
解决措施(1):增加堆大小(本人部署应用的服务器内存总16GB,可用内存约4.3GB)
①将最大堆大小(-Xmx)设置为3GB,初始堆大小(-Xms)设置为2GB。--导到178585条数据时触发
java.lang.OutOfMemoryError related to the Java heap space. Java 堆空间不足
②将最大堆大小(-Xmx)设置为4GB,初始堆大小(-Xms)设置为2GB。--21万可以正常导出。超过213214条数据时触发 java.lang.OutOfMemoryError related to the Java heap space. Java 堆空间不足
解决措施(2):优化代码
本文采用了缓冲写入
修改前代码:
public void writeExcel(OutputStream os, String sheetName, Map<String, String> header, List<Map<String, Object>> datas) {
logger.info("导入数据到excel==========> start");
long startTime = System.currentTimeMillis(); // 记录开始时间
XSSFWorkbook wb = null;
try {
wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet(sheetName);
int rowNum = 0;
XSSFRow row = sheet.createRow(rowNum);
Map<String, CellStyle> cellstyles = initStyles(wb);
int cellNum = 0;
for (Map.E