jvm内存泄漏

jvm内存泄漏内存泄漏和内存溢出的关系内存泄露:指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存。即被分配的对象可达但已无用。内存溢出:指程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。从定义上可以看出内存泄露是内存溢出的一种诱因,但是不是唯一因素。可以使用Runtime.ge…

大家好,又见面了,我是你们的朋友全栈君。

文章出自于:https://www.itqiankun.com/article/1564247928

内存泄漏和内存溢出的关系

内存泄露:指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存。即被分配的对象可达但已无用。
内存溢出:指程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。
从定义上可以看出内存泄露是内存溢出的一种诱因,但是不是唯一因素。

可以使用Runtime.getRuntime().freeMemory()进行内存泄漏查询

Runtime.getRuntime().freeMemory()表示当前还有多少空闲内存

package com.one.util;

public class Hello { 
   
    public static void main(String[] args) { 
   
        System.out.println("free内存:" + Runtime.getRuntime().freeMemory() / 1024
            / 1024);
        String[] aaa = new String[2000000];
        for (int i = 0; i < 2000000; i++) { 
   
            aaa[i] = new String("aaa");
        }
        System.out.println("free内存:" + Runtime.getRuntime().freeMemory() / 1024 / 1024);
    }
}

此时结果如下所示
在这里插入图片描述

内存泄漏的例子

如果长生命周期的对象持有短生命周期的引用,就很可能会出现内存泄露

比如下面的代码,这里的object实例,其实我们期望它只作用于method1()方法中,且其他地方不会再用到它,但是,当method1()方法执行完成后,object对象所分配的内存不会马上被认为是可以被释放的对象,只有在Simple类创建的对象被释放后才会被释放,严格的说,这就是一种内存泄露。

public class Simple { 
   
 
    Object object;
 
    public void method1(){ 
   
        object = new Object();
        //...其他代码
    }
}


怎么解决上面的问题呢,加上下面的蓝色代码注释就好了

public class Simple { 
   
 
    Object object;
 
    public void method1(){ 
   
        object = new Object();
        //...其他代码
        // 蓝色代码注释开始
        object = null;
        // 蓝色代码注释结束
    }
}

集合里面的内存泄漏

集合里面的数据都设置成null,但是集合内存还是存在的

比如下面的代码
因为你已经在下面的蓝色代码注释里面进行company=null了,所以下面的list集合里面的数据都是无用的了,但是此时list集合里面的所有元素都不会进行垃圾回收

package com.four;

import java.util.ArrayList;
import java.util.List;

public class Hello { 
   
    public static void main(String[] args) { 
   
        List<Company> list = new ArrayList<Company>();
        int i=0;
        for(int j=0;j<10;j++){ 
   
            Company company = new Company();
            company.setName("ali");
            list.add(company);
            // 蓝色代码注释开始
            company = null;
            // 蓝色代码注释结束
        }

        System.gc();
        while(true){ 
   
            try { 
   
                Thread.sleep(1000);
            } catch (InterruptedException e) { 
   
                e.printStackTrace();
            }
            System.out.println("已经测试了"+(++i)+"秒");
        }
    }

}


class Company { 
   
    private String name;

    @Override
    protected void finalize() throws Throwable { 
   
        super.finalize();
        System.out.println("回收Comapny");
    }

    public void setName(String name) { 
   
        this.name = name;
    }

    public String getName() { 
   
        return name;
    }
}

在这里插入图片描述
怎么解决上面的问题呢,就是把上面的list集合变量也变成null,比如加上下面的红色代码注释

package com.one.util;

import java.util.ArrayList;
import java.util.List;

public class Hello { 
   
    public static void main(String[] args) { 
   
        List<Company> list = new ArrayList<Company>();
        int i = 0;
        for (int j = 0; j < 10; j++) { 
   
            Company company = new Company();
            company.setName("ali");
            list.add(company);
            // 蓝色代码注释开始
            company = null;
            // 蓝色代码注释结束
        }
        // 红色代码注释开始
        list = null;
       // 红色代码注释结束
        System.gc();
        while (true) { 
   
            try { 
   
                Thread.sleep(1000);
            } catch (InterruptedException e) { 
   
                e.printStackTrace();
            }
            System.out.println("已经测试了" + (++i) + "秒");
        }
    }

}

class Company { 
   
    private String name;

    @Override
    protected void finalize() throws Throwable { 
   
        super.finalize();
        System.out.println("回收Comapny");
    }

    public void setName(String name) { 
   
        this.name = name;
    }

    public String getName() { 
   
        return name;
    }
}

此时结果如下所示,可以看出来集合里面的Company变量都回收了
在这里插入图片描述

还有就是使用remove()方法进行移除元素的时候,也可能会造成内存泄漏

什么意思呢,
就比如ArrayList里面的pop(),如果是下面的写法就会造成内存泄漏,因为下面的elementData[–size]这个元素移除之后,并没有进行设置成null

public E pop(){ 
   
    if(size == 0)
        return null;
    else
        return (E) elementData[size];
}

所以上面的代码应该变成下面这样,此时注意下面的蓝色代码注释里面的size值比下面的红色代码注释里面的size小1

public E pop(){ 
   
    if(size == 0)
        return null;
    else{ 
   
        // 红色代码注释开始
        E e = (E) elementData[--size];
        // 红色代码注释结束
        // 蓝色代码注释开始
        elementData[size] = null;
        // 蓝色代码注释结束
        return e;
    }
}

连接没有关闭会泄漏

比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,这些链接在使用的时候,除非显式的调用了其close()方法(或类似方法)将其连接关闭,否则是不会自动被GC回收的。其实原因依然是长生命周期对象持有短生命周期对象的引用。所以我们经常在网上看到在连接调用结束的时候要进行调用close()进行关闭,这样可以回收不用的内存对象,增加可用内存。

能看到这里的同学,就帮忙右上角点个赞吧,Thanks♪(・ω・)ノ

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/137934.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Ajax教程_ajax是服务器端动态网页技术

    Ajax教程_ajax是服务器端动态网页技术Ajax教程Ajax能做什么Ajax是一种异步请求数据的web开发技术,目前主要用于异步,大家都知道,浏览器主线程是单线程的,也就是一次只能干一件事,以Ajax就是让浏览器当主线程完成后去干别的事

  • Java基础入门笔记08——文件流,IO流,FileIputStream类,FileOutputStream类,缓冲流,转换流,标准输入输出流,打印流,数据流,对象流,随机存储流

    Java基础入门笔记08——文件流,IO流,FileIputStream类,FileOutputStream类,缓冲流,转换流,标准输入输出流,打印流,数据流,对象流,随机存储流IO流java.io.File类——对计算机操作系统中的文件和文件夹文件流——基于文件的操作,一般都以File开头缓冲流——基于内存的操作,一般都以BuffereDd开头转换流标准输入输出流打印流——PrintStream/PrintWriter——System.out.println数据流对象流——把一个对象转换为数据流进行读写,涉及到序列化、反序列化随机存取文件流——这里的随机是指随意,想在哪里进行就在哪里进行,进行的操作也是可以随意指定的相对路

  • redisson读写锁使用场景_Redisson酒店

    redisson读写锁使用场景_Redisson酒店读写锁一次只有一个线程可以占有写模式的读写锁,但是可以有多个线程同时占有读模式的读写锁.正是因为这个特性,当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞.当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是如果线程希望以写模式对此锁进行加锁,它必须直到所有的线程释放锁.通常,当读写锁处于读模式锁住状态时,如果有另外线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁请求,这样可以避免读模式锁长期占用,而等待的写模式

  • [学习笔记]上传文件到EC2主机[通俗易懂]

    [学习笔记]上传文件到EC2主机[通俗易懂]之前在别的主机服务器上上传到文件,过程如下:首先有ssh连接,不管是通过输入密码的方式还是添加密钥的方式都一样,确定建立链接没有问题之后,就有下面的操作sshhostname@public_ip//建立链接mkdirupload//创建接受文件的文件夹chmod777uploadscppath_to_filehostname@public_ip:/home/hostnam

  • android toast用法_android五种布局的特点

    android toast用法_android五种布局的特点Toast用于向用户显示一些帮助/提示。下面我做了5中效果,来说明Toast的强大,定义一个属于你自己的Toast。1.默认效果代码Toast.makeText(getApplicationContext(),"默认Toast样式",     Toast.LENGTH_SHORT).show(); 2.自定义显示位置效果代码toast=Toast.mak…

  • ResNet 18 的结构解读「建议收藏」

    ResNet 18 的结构解读「建议收藏」现在很多网络结构都是一个命名+数字,比如(ResNet18),数字代表的是网络的深度,也就是说ResNet18网络就是18层的吗?其实这里的18指定的是带有权重的18层,包括卷积层和全连接层,不包括池化层和BN层。下面先贴出ResNet论文中给出的结构列表。对Pytorch中ResNet18网络的源码分析(这里),我画出了大致的网络结构图。可以看出,数字18=17个…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号