【案例一】验证CSVParser和RandomAccessFile的内存表现
借助RandomAccessFile和apache.commons.csv包分别解析CSV
CSVParser
首先设置JVM内存为32M,生成CSV文件超过内存
-Xms32m -Xmx32m
public class MyTest {
public static void main(String[] args) throws IOException, SQLException {
System.gc();
createCsv();
readCsv();
}
public static void createCsv() throws IOException {
if (Files.exists(new File("C:\\Users\\g30038553\\Desktop\\temp\\话单jilu\\test.csv").toPath())) {
return;
}
String s = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
FileWriter fw = new FileWriter("C:\\Users\\my\\Desktop\test.csv", true);
for (int i = 0; i < 100000; i++) {
fw.write(s);
fw.write('\n');
fw.flush();
}
}
public static void readCsv() throws IOException {
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
memoryMXBean.setVerbose(true);
MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
long heapMemoryUsaged;
long nonHeapMemoryUsaged;
heapMemoryUsaged = heapMemoryUsage.getUsed();
System.out.println("Heap Memory Usage - init: " + heapMemoryUsaged);
nonHeapMemoryUsaged = nonHeapMemoryUsage.getUsed();
System.out.println("nonHeap Memory Usage - init: " + nonHeapMemoryUsaged);
File file = new File("C:\\Users\\my\\Desktop\test.csv");
heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
heapMemoryUsaged = heapMemoryUsage.getUsed();
System.out.println("Heap Memory Usage - newFile: " + heapMemoryUsaged);
nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
nonHeapMemoryUsaged = nonHeapMemoryUsage.getUsed();
System.out.println("nonHeap Memory Usage - newFile: " + nonHeapMemoryUsaged);
CSVFormat defaultFormat = CSVFormat.DEFAULT;
heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
heapMemoryUsaged = heapMemoryUsage.getUsed();
System.out.println("Heap Memory Usage - newFormat: " + heapMemoryUsaged);
nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
nonHeapMemoryUsaged = nonHeapMemoryUsage.getUsed();
System.out.println("nonHeap Memory Usage - newFormat: " + nonHeapMemoryUsaged);
CSVParser parse = CSVParser.parse(file, Charset.defaultCharset(), defaultFormat);
heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
heapMemoryUsaged = heapMemoryUsage.getUsed();
System.out.println("Heap Memory Usage - newParser: " + heapMemoryUsaged);
nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
nonHeapMemoryUsaged = nonHeapMemoryUsage.getUsed();
System.out.println("nonHeap Memory Usage - newParser: " + nonHeapMemoryUsaged);
List<CSVRecord> records = parse.getRecords();
heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
heapMemoryUsaged = heapMemoryUsage.getUsed();
System.out.println("Heap Memory Usage - getRecords: " + heapMemoryUsaged);
nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
nonHeapMemoryUsaged = nonHeapMemoryUsage.getUsed();
System.out.println("nonHeap Memory Usage - getRecords: " + nonHeapMemoryUsaged);
System.out.println(records);
}
}
CSVParser解析结果显示:
Heap Memory Usage - init: 16790296
nonHeap Memory Usage - init: 6021568
Heap Memory Usage - newFile: 16790296
nonHeap Memory Usage - newFile: 6149160
Heap Memory Usage - newFormat: 16790296
nonHeap Memory Usage - newFormat: 6294384
Heap Memory Usage - newParser: 17838872
nonHeap Memory Usage - newParser: 6392208
……
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
……
堆内存结果显示,构造CSVParser的过程中,堆外内存持续增长,堆内存增长不明显,但最终getRecords时堆内存抛出OOM异常
将重复写字符串的次数调整到5000,再次执行
Heap Memory Usage - init: 16802896
nonHeap Memory Usage - init: 6013848
Heap Memory Usage - newFile: 16802896
nonHeap Memory Usage - newFile: 6133896
Heap Memory Usage - newFormat: 16802896
nonHeap Memory Usage - newFormat: 6288328
Heap Memory Usage - newParser: 17851472
nonHeap Memory Usage - newParser: 6383848
可见在getRecords阶段是堆内存增长的来源
评论区