关于链表的清空(防止内存泄漏)


构建链表之后为什么要将链表清空?

  链表是用指针把一个个存储的空间连接起来了,用完之后不清空,很容易发生内存泄漏(内存泄漏:向系统申请分配内存进行使用(new),可是使用完了以后却不delete,而自己出于某些原因不能再访问到那块内存(也许把它的地址给弄丢了),这时候系统也不能再次将它分配给需要的程序。)

JVM内存回收

   jvm内存结构分为五大区域:程序计数器、虚拟机栈、本地方法栈、堆区、方法区。其中虚拟机栈、本地方法栈与程序计数器这3个区域随线程而生、随线程而灭,因此就不需要考虑过多内存垃圾回收问题,一个方法调用结束或者线程结束时,内存自然就跟随着回收了。而方法区与堆区,这部分内存的分配和回收是动态的。

垃圾回收器

  那么哪些可以回收,哪些不能回收呢?
垃圾收集器在对堆区和方法区进行回收工作前,首先肯定确定这些区域内对象哪些可以被回收,哪些暂时还不能回收,这时就要用到判断对象是否存活的算法,如何失去任何引用,垃圾收集器就把它收走。

   
1.单链表的清空:

class ListNode{
    public int data;
    public ListNode next;

    public ListNode(int data){
        this.data=data;
        this.next=null;
    }
}//节点类


class MyLinkList{
    public ListNode head;

    public MyLinkList(){
        this.head=null;
    }


    //尾插法建立
    public void addLast(int data){
        ListNode node=new ListNode(data);
        if(this.head==null){
           this.head=node;
        }else{
            ListNode cur=this.head;
            while(cur.next!=null){
                cur=cur.next;
            }
            cur.next=node;
        }
    }

    public void display(){
        ListNode cur=this.head;
        while(cur!=null){
            System.out.print(cur.data+" ");
            cur=cur.next;
        }
        System.out.println();
    }

    //清空单链表
    public void clear(){
        //1.将每一个next域都置为空,JVM自动回收掉没有引用的节点
        while(this.head!=null){
            ListNode cur=this.head.next;
            this.head.next=null;
            this.head=cur;
        }
    }
}


public class Test {
    public static void main(String[] args) {
        MyLinkList my = new MyLinkList();
        my.addLast(3);
        my.addLast(4);
        my.addLast(5);
        my.addLast(6);
        my.display();
        System.out.println("------------");
        my.clear();
        my.display();
        System.out.println("------------");
    }
}


//打印结果
3 4 5 6 
------------

------------




2.双向链表的清空:

class ListNode{
    public int data;
    public ListNode prev;
    public ListNode next;


    public ListNode(int data){
        this.data=data;
    }
}//节点类

class DoubleList {
    public ListNode head;
    public ListNode last;

    //头插法
    public void addFirst(int data) {
        ListNode node = new ListNode(data);
        if (this.head == null) {
            this.head = node;
            this.last = node;
        } else {
            node.next = this.head;
            this.head.prev = node;
            this.head = node;
        }
    }

    public void display() {
        if (this.head == null) {
            return;
        }
        ListNode cur = this.head;
        while (cur != null) {
            System.out.print(cur.data + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    //清空
    public void clear() {
        while (this.head != null) {
            ListNode cur = this.head.next;
            this.head.prev = null;
            this.head.next = null;
            this.head = cur;
        }
        this.last = null;
    }
}




public class Test {
    public static void main(String[] args) {
        DoubleList doubleList = new DoubleList();
        doubleList.addFirst(1);
        doubleList.addFirst(2);
        doubleList.addFirst(3);
        doubleList.addFirst(4);
        doubleList.addFirst(5);
        doubleList.display();
        System.out.println("-------------");
        doubleList.clear();
        doubleList.display();
    }
}


//打印结果
5 4 3 2 1 
-------------





接下来打断点测试一下是否内存已经被清空(以双向链表为例子)

  在命令框中输入以下图中命令

 1.jps命令:指仅查找当前用户的Java进程,而不是当前系统中的所有进程
 2.当服务发生GC问题时,一般会使用jmap工具进行分析
    jmap -histo[:live]
通过histo选项,打印当前java堆中各个对象的数量、大小。
在这里添加了live,只会打印活跃的对象。

在这里插入图片描述
命令执行完毕,即在e盘中产生一个log.txt的文本文档
在这里插入图片描述
用Notepad++打开上图log.txt文本文档
在这里插入图片描述
此时可以看到已经查找不到节点了,即链表被清空

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值