关于链表的清空(防止内存泄漏)
构建链表之后为什么要将链表清空? 链表是用指针把一个个存储的空间连接起来了,用完之后不清空,很容易发生内存泄漏(内存泄漏:向系统申请分配内存进行使用(new),可是使用完了以后却不delete,而自己出于某些原因不能再访问到那块内存(也许把它的地址给弄丢了),这时候系统也不能再次将它分配给需要的程序。)JVM内存回收 jvm内存结构分为五大区域:程序计数器、虚拟机栈、本地方法...
构建链表之后为什么要将链表清空?
链表是用指针把一个个存储的空间连接起来了,用完之后不清空,很容易发生内存泄漏(内存泄漏:向系统申请分配内存进行使用(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文本文档
此时可以看到已经查找不到节点了,即链表被清空
更多推荐
所有评论(0)