实验环境
Windows 10 19043.1348
JDK 1.8.0_311
JVM参数:-Xms500m -Xmx500m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
实验设置
两个参数:
maxCachedBufferSize - 表示最大缓存的buffer大小,超过这个大小的buffer不放入bufferCache,直接释放
readBufferSize - 一次读文件读取的buffer大小
三种情况:
单线程
循环开n个线程
大小为n的线程池
四种读文件模式:
每个线程从同一个文件读一次(读取位置随机,下同)
每个线程从同一个文件不断读取
每个线程从不同文件读读一次
每个线程从不同文件不断读取
使用 Java VisualVM 观察线程活跃情况以及堆外内存占用情况。(需加装插件 BufferMonitor)
实验结果
实验1:readBufferSize > MaxDirectMemorySize
readBufferSize 设置为 6 M, 无论 maxCachedBufferSize 大小如何设置,都直接OOM
实验2:readBufferSize > MaxDirectMemorySize,readBufferSize > maxCachedBufferSize
static long maxCachedBufferSize = 1024 * 1024 * 1;
static int readBufferSize = 1024 * 1024 * 2;
1、单线程,从文件随机读取一段
读取成功,未观测到堆外内存占用
2、单线程,从同一个文件不断读取
读取成功
3、循环多线程,从文件随机读取一段
static int threadNum = 2;
读取成功,未观测到堆外内存占用
static int threadNum = 100;
发生OOM,有42个线程读取成功
4、循环多线程,从文件不断读取
static int threadNum = 2;
读取成功
static int threadNum = 100;
发生OOM,最后只剩下两个线程
5、线程池,从文件随机读取一段
static int threadNum = 2;
读取成功,未观测到堆外内存占用
static int threadNum = 100;
发生OOM,55个线程读取成功
6、线程池,从文件不断读取
static int threadNum = 2;
读取成功
static int threadNum = 100;
发生OOM,只剩下两个线程活跃,其他线程驻留
实验3:readBufferSize > MaxDirectMemorySize,readBufferSize < maxCachedBufferSize
static long maxCachedBufferSize = 1024 * 1024 * 2;
static int readBufferSize = 1024 * 1024 * 1;
1、单线程,从文件随机读取一段
读取成功,未观测到
2、单线程,从同一个文件不断读取
读取成功,
3、循环多线程,从文件随机读取一段
static int threadNum = 5;
读取成功,未观测到
static int threadNum = 100;
成功读取5次后OOM,
4、循环多线程,从文件不断读取
static int threadNum = 5;
读取成功
static int threadNum = 100;
只有5个线程活跃,其他线程休眠,未爆OOM
5、线程池,从文件随机读取一段
static int threadNum = 5;
读取成功,
static int threadNum = 100;
5个线程读取成功后发生OOM
6、线程池,从文件不断读取
static int threadNum = 5;
读取成功,
static int threadNum = 100;
发生OOM,只有五个线程活跃
下一步,对参数 TEMP_BUF_POOL_SIZE 进行验证,但现在还没模拟出来。