1. Linux下内存的概念
a. 虚拟内存(VIRT): 每个进程都有自己的虚拟内存,顾名思义就是虚拟的,和机器的实际内存无关;
b. 驻留内存(RES):每个进程占用的实际物理内存;
每个进程虚拟内存和驻留内存使用情况可以调用top进行监控。
注:本文是为了研究JNA内存情况顺便总结的,测试完整代码在后文可以下载
2. 虚拟内存的泄露
测试代码如下:
struct _BigMemory
{
int mem[20000000];
};
typedef struct _BigMemory BigMemory;
void checkVirMemLeak()
{
BigMemory *bigMemory = NULL;
while(1)
{
bigMemory = (BigMemory *)malloc(sizeof(BigMemory));
sleep(5);
}
}
现象:
代码中调用如上代码可以看到进程每隔5s,虚拟内存就会增加80M,但是驻留内存不会增加。
分析:
每个进程的虚拟内存都是固定的,程序中malloc内存的时候,虚拟内存就会增加,但是如果不使用这段内存,程序并不会向内核申请内存。借用我当初老板Kerry的一句话:
虚拟内存就是你存在银行的钱,驻留内存就是你从取款机取钱。实际机器并不能满足所有进程如果都把自己虚拟内存申请过来使用,这就是挤兑银行了。:)
每个进程的虚拟内存都有上限,和32位64位相关,所有虚拟内存也不能无限增加,程序不停申请虚拟内存也是一种内存泄露,当所有的虚拟内存都申请完了,程序就要挂了。
3. 虚拟内存和驻留内存的示例
测试代码如下:
void checkVirResMemLeak()
{
BigMemory *bigMemory = NULL;
int i = 0;
while(1)
{
bigMemory = (BigMemory *)malloc(sizeof(BigMemory));
for(i=0; i<20000000; i++)
{
bigMemory->mem[i] = 3;
}
sleep(5);
}
}
现象:
代码中调用如上代码可以看到进程每隔5s,虚拟内存和驻留内存都会增加80M。
分析:
这个程序每次申请80M内存,自然虚拟内存会增加80M。申请完以后会给每个值赋值,程序会中断内核分配实际物理内存,所以驻留内存会增加80M,这样等不到虚拟内存使用完,当实际物理内存不够分配时,程序也会挂了(不考虑swap分区情况)。
4. 无内存泄露示例
测试代码:
void checkNonMemLeak()
{
BigMemory *bigMemory = NULL;
int i = 0;
while(1)
{
bigMemory = (BigMemory *)malloc(sizeof(BigMemory));
for(i=0; i<20000000; i++)
{
bigMemory->mem[i] = 3;
}
free(bigMemory);
sleep(5);
}
}
现象:
虚拟内存和驻留内存都会恒定