如何测试是否存在内存泄漏

如何测试内存泄漏

命令:

jps
 jmap -histo:live [进程号] > [文件路径]

命令解释:

  • jps:查看当前代码的进程号;
  • jmap -histo:live [进程号] > [文件路径]:讲得到的信息放到某一个文件下,运行后打开此文件,查看还有多少个实例。

具体实现:

  1. 在测试代码中加上一句 Thread.sleep(1000); 并在这个地方打上一个断点,随后进入debug调试模式;
  2. 在键盘上菜单键+R进入cmd 命令环境;
  3. 输入 jps 命令查看当前运行的程序的进程号;
  4. 利用进程号,输入 jmap -histo:live [进程号] > [文件路径] 命令,其中文件路径可以随意定义但不要在项目里;
  5. 回到项目中,令debug调试进入下一步,在cmd中的上一个命令就会运行完成而产生对应的文件;
  6. 打开文件,Ctrl + F 查看程序运行完后引用对象的个数,不为0则代表存在内存泄漏。

实例

顺序表的插入:

package com.github.sqlist;
import java.lang.*;
import java.util.Arrays;

public class MySequenceImpl implements ISequence {

    private Object[] elem;
    // 有效数据个数
    private int usedSize;
    private static final int DEFAULT_SIZE = 10;

    public MySequenceImpl() {
        this.elem = new Object[DEFAULT_SIZE];
        this.usedSize = 0;
    }

    // 判断是否为满
    private boolean isFull() {
        return this.usedSize == this.elem.length;
    }

    /**
     * 在 pos 位置插入 val
     * @param pos 要插入的位置
     * @param data 插入的值
     * @return 成功插入true,否则false
     */
    @Override
    public boolean add(int pos, Object data) {
        // 1. pos 位置的合法性进行判断
        if (pos<0 || pos>DEFAULT_SIZE) {
            return false;
        }
        // 2. 判断是否为满
        if (isFull()) {
            // 2 倍扩容
            // 拷贝数组:System.arraycopy(); / Arrays.copyOf(); (区别:后者有返回值)
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }

        for (int i = this.usedSize-1; i >= pos; i--) {
            this.elem[i+1] = this.elem[i];
        }
        this.elem[pos] = data;
        usedSize++;
        return true;
    }

    /**
     * 打印顺序表
     */
    @Override
    public void display() {
        for (int i = 0; i < this.usedSize; i++) {
            System.out.print(this.elem[i] + " ");
        }
        System.out.println();
    }
}

测试代码:

package com.github.sqlist;

class Person {

}

public class TestDemo1 {
    public static void main(String[] args) {
        MySequenceImpl mySequence = new MySequenceImpl();

        mySequence.add(0,new Person());
        mySequence.add(1,new Person());
        mySequence.add(2,new Person());
        mySequence.display();
        
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

  1. 在cmd中 运行 jps 命令:得到进程号 40324
    如何测试是否存在内存泄漏_第1张图片
  2. 继续输入命令:jmap -histo:live 40324> C:\Data\log.txt
  3. 回到代码中令debug调试进入下一步,上一个命令完成,log.txt随即保存保存到C:\Data\log.txt 的路径下
    在这里插入图片描述
  4. 打开log.txt 文件,ctrl+F查找 Person
    在这里插入图片描述
    有三个Person对象。(如:Person对象有3个,在log.txt中的#instances列表示为3)

写一个方法清空顺序表以防内存泄漏:

/**
     * 清空顺序表以防内存泄漏
     */
    @Override
    public void clear() {
        for (int i = 0; i < this.usedSize; i++) {
            this.elem[i] = null;
        }
    }

测试:

package com.github.sqlist;

class Person {

}

public class TestDemo1 {
    public static void main(String[] args) {
        MySequenceImpl mySequence = new MySequenceImpl();

        mySequence.add(0,new Person());
        mySequence.add(1,new Person());
        mySequence.add(2,new Person());
        mySequence.display();
        // 无clear则会内存泄漏
        mySequence.clear();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

再一次执行命令查看:Jps、jmap -histo:live 38780 > C:\Data\log.txt
无clear则会内存泄漏
如何测试是否存在内存泄漏_第2张图片

你可能感兴趣的:(Java)