欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-08 23:39:52
...


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

  链表是用指针把一个个存储的空间连接起来了,用完之后不清空,很容易发生内存泄漏(内存泄漏:向系统申请分配内存进行使用(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文本文档
关于链表的清空(防止内存泄漏)
此时可以看到已经查找不到节点了,即链表被清空

相关标签: 链表