实验环境

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的线程池

四种读文件模式:(文件大小80M,每次读取位置随机)

每个线程从同一个文件读一次

每个线程从同一个文件不断读取

每个线程从不同文件读读一次

每个线程从不同文件不断读取

使用 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后退出

另一种情况:其他线程短暂休眠(0.5s左右)之后退出

原因解释:申请内存失败时会短暂等待,等待的最长时间是0.5s左右

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 进行验证,但现在还没模拟出来。


FileChannelBufferTest.java


  • No labels