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

内存泄露:指程序中动态分配内存给一些临时对象,但是对象不会被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♪(・ω・)ノ

原文链接

Jvm内存泄漏的更多相关文章

  1. Java JVM 内存泄漏--全解析和处理办法 [ 转载 ]

    Java JVM 内存泄露——全解析和处理办法 [转载]   @author 小筐子 @address http://www.jianshu.com/p/bf159a9c391a         JA ...

  2. 排查JVM内存泄漏的命令

    1. jps 使用 jps -l -m 获取到当前jvm进程的pid,通过上述命令获取到了服务的进程号 jps(JVM Process Status Tool):显示指定系统内所有的HotSpot虚拟 ...

  3. jconsole工具使用----jvm内存泄漏问题

    转载地址:https://www.cnblogs.com/baihuitestsoftware/articles/6405580.html Jconsole,Java Monitoring and M ...

  4. java.lang.OutOfMemoryError: PermGen space (jvm内存泄漏解决办法)

    2.在myeclipse根目录 打开myeclipse.ini 3.在myeclipse中配置内存

  5. 快速串讲——JVM内存的区域划分

    目的 快速定位JVM内存泄漏或者溢出等问题. 面试基础题,加分项. 文章持续更新,微信搜索「万猫学社」第一时间阅读,关注后回复「电子书」,免费获取12本Java必读技术书籍. 程序计数器(Progra ...

  6. Java内存泄漏分析系列之六:JVM Heap Dump(堆转储文件)的生成和MAT的使用

    原文地址:http://www.javatang.com JVM Heap Dump(堆转储文件)的生成 正如Thread Dump文件记录了当时JVM中线程运行的情况一样,Heap Dump记录了J ...

  7. 运维-JVM监控之内存泄漏

    转载:https://blog.csdn.net/zdx_csdn/article/details/71214219 jmap -heap pid查看进程堆内存使用情况,包括使用的GC算法.堆配置参数 ...

  8. JVM的内存管理、对象的生命周期、内存泄漏

    1 JVM内存 分为“堆”.“栈”和“方法区”三个区域,分别用于存储不同的数据 1.1 堆 JVM在其内存空间开辟一个称为”堆”的存储空间,这部分空间用于存储使用new关键字所创建的对象. 1.2 栈 ...

  9. 说说JVM原理?内存泄漏与溢出的区别?何时产生内存泄漏?

    1.JVM原理 JVM是Java Virtual Machine(Java虚拟机)的缩写,它是整个java实现跨平台的最核心的部分,所有的Java程序会首先被编译为.class的类文件,这种类文件可以 ...

随机推荐

  1. C# 管道式编程

    受 F# 中的管道运算符和 C# 中的 LINQ 语法,管道式编程为 C# 提供了更加灵活性的功能性编程.通过使用 扩展函数 可以将多个功能连接起来构建成一个管道. 前言 在 C# 编程中,管道式编程 ...

  2. 当没有接口时、不可继承时,如果使用mock方案进行单元测试

    原版代码: import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; imp ...

  3. 我这边测了一下,发现#后面参数变化浏览器不会刷新,但是#一旦去掉就会刷新了,你那边的url拼的时候能不能在没参数的时候#也拼在里面,这样应该就OK了

    我这边测了一下,发现#后面参数变化浏览器不会刷新,但是#一旦去掉就会刷新了,你那边的url拼的时候能不能在没参数的时候#也拼在里面,这样应该就OK了

  4. UVA12657 Boxes in a Line:题解

    题目链接:https://www.luogu.org/problemnew/show/UVA12657 分析: 此题使用手写链表+模拟即可.(其实可以用list,而且更简便,但是会大大的超时) 肯定是 ...

  5. Kafka工作流程分析

    Kafka工作流程分析 生产过程分析 写入方式 producer采用推(push)模式将消息发布到broker,每条消息都被追加(append)到分区(patition)中,属于顺序写磁盘(顺序写磁盘 ...

  6. python3.x 与 python2.x 差别记录

    从2.x过渡到3.x的时候,遇到了大大小小的坑,于是便记录下来- 1.print:  3.x 所有print都要加 "( )",print更像(就是)一个函数了. 2.x 可以加& ...

  7. es6的基本用法

    1. let和const <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  8. jenkins默认在build结束后会kill掉所有的衍生进程

    在使用jenkins进行自动化部署服务的过程中,发现调用服务器的shell命令无法正常启动tomcat,但是构建日志显示是成功执行的,而手动在服务器却是可以正常启动tomcat. 原因:jenkins ...

  9. Tomcat(Linux)

    百度云:链接:http://pan.baidu.com/s/1o7MNTJc    密码:cfof 官方下载网址:http://archive.apache.org/dist/tomcat/tomca ...

  10. maven打包添加依赖

    <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <versio ...