java之内存泄露

一、过期引用导致的内存泄露

注意:当对象不使用后将对象设置为null,这个时候虚拟机不一定释放该内存,至于什么时候释放由垃圾回收算法确定。

当对象不在使用时,而不回收有可能出现内存泄露的问题。在Effective Java里面有一条建议,消除过期的对象引用。

实例:JDK中栈的内存优化问题

1、消除过期对象引用的原因(出现内存泄露的原因):随着栈的增加,然后再收缩,从栈中出来的对象将不会被回收,即使程序不在引用这些对象。

因为,在栈的内部维护着这些对象的过期引用(过期引用就是永远不会被解除的引用)。

2、内存泄露过程:随着垃圾回收器的活动,或者说内存占用的不断增加,程序的性能变低会慢慢显示出来。在极端的情况下,程序很容易出现OOM的错误。

下面的程序模拟JDK中Stack的实现:

public class MyStack {
	private Object[] elements;// 栈用来装元素的
	private int size = 0;// 栈的大小
	private static final int DEFALT_INITIAL_CAPACITY = 16;

	public MyStack(){
		elements = new Object[DEFALT_INITIAL_CAPACITY];
	}

	/*
	 * 入栈
	 */
	public void push(Object e) {
		ensureCapacity();
	}

	/**
	 * 出栈
	 */
	public Object pop() {
		if(size==0)
			throw new EmptyStackException();
		return elements[--size];
	}

	/**
	 * 动态扩展栈的空间,确保栈中有足够的空间
	 */
	private void ensureCapacity() {
		if(elements.length==size) {
			elements = Arrays.copyOf(elements, 2*size+1);
		}
	}
}

二、hashCode与内存泄露:

public class MemoryLeakDemo {

	public static void main(String[] args) {
		Point p1 = new Point(1,2);
		Point p2 = new Point(3,4);
		Point p3 = new Point(3,6);
		Collection<Point> c = new HashSet<Point>();
		c.add(p1);
		c.add(p2);
		c.add(p3);
		c.add(p1);
		System.out.println("原来的对象数量:"+c.size());
	    // p1.setX(5);
	    c.remove(p1);
	    System.out.println("处理后的对象数量:"+c.size());// 原来有三个对象,删除后还有两个,打开上面的注释后,变成三个。
	}

}

class Point {
	private int x;
	private int y;

	public Point(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Point other = (Point) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}
}

原来有3个对象,删除后还有2个,打开上面的注释后,变成3个。为什么会对象删不掉呢?因为修改hashCode后,这个对象所在存储区域发生变化(哈希查找基本思路:通过计算对象的哈希码,然后进行哈希码分组,将对象存储到不同的区域,当需要对象时只需通过哈希码就可以确定对象属于哪个存储区域,从而加快了查找效率),执行remove方法后对象没有被删除,所以仍然是这么多元素。因为不用的对象占着内存不释放,所以出现了内存泄露的问题。那么,随着增删操作元素的次数不断增加,内存的耗用越来越大,从而导致程序异常结束。

时间: 2024-10-25 14:24:28

java之内存泄露的相关文章

java的内存泄露是如何发生的,如何避免和发现?

java的垃圾回收与内存泄露的关系:[新手可忽略不影响继续学习] (视频下载) (全部书籍) 马克-to-win:上一节讲了,(i)对象被置成null.(ii)局部对象(无需置成null)当程序运行到右大括号.(iii)匿名对象刚用完,垃圾回收线程就早早晚晚都能把它过去占的内存给回收了.这么说,java中难道就没有c++的内存泄露的问题了吗?(内存泄露的定义就是: 咱自己程序不用的内存,系统本应回收但由于各种原因却没有回收成功)马克-to-win:答案: 错,java中有内存泄露.下面我们就通过

java的内存泄露

java的内存泄露 来源:http://www.sxt.cn/Java_jQuery_in_action/The_operation_of_memory_leakage_in_development.html 在实际开发中,经常会造成系统的崩溃.如下这些操作我们应该注意这些使用场景. 创建大量无用对象: 比如,我们在需要大量拼接字符串时,使用了String而不是StringBuilder. String str = ""; for (int i = 0; i < 10000; i

Java中内存泄露及垃圾回收机制

3 垃圾回收机制 3.1 什么是垃圾 垃圾,内存中的垃圾,即内存中已无效但又无法自动释放的空间.在Java语言中,没有引用句柄指向的类对象最容易成为垃圾.,产生垃圾的情况有很多,主要有以下3种: (1)       超出对象的引用句柄的作用域时,这个引用句柄引用的对象就变成垃圾. 例: { Person p1 = new Person(); …… } 引用句柄p1的作用域是从定义到“}”处,执行完这对大括号中的所有代码后,产生的Person对象就会变成垃圾,因为引用这个对象的句柄p1已超过其作用

JAVA NIO 内存泄露

写NIO程序经常使用ByteBuffer来读取或者写入数据,那么使用ByteBuffer.allocate(capability)还是使用ByteBuffer.allocteDirect(capability)来分配缓存了?第一种方式是分配JVM堆内存,属于GC管辖范围,由于需要拷贝所以速度相对较慢:第二种方式是分配OS本地内存,不属于GC管辖范围,由于不需要内存拷贝所以速度相对较快. 我们肯定想选择比较快的,但问题是直接内存不属于GC管辖范围,需要弄清楚这部分内存如何管理,否则造成内存泄露就麻

JAVA简单内存泄露分析及解决

一.问题产生    项目采用Tomcat6.0为服务器,数据库为mysql5.1,数据库持久层为hibernate3.0,以springMVC3.0为框架,项目开发完成后,上线前夕进行稳定性拷机,测试数据为插入4条/S,更新4条/S,访问300次/S,前期运行速度顺畅,三天后就开始运行缓慢,访问量达到1500W次后以抛出Java heap space结束.二.问题分析    1.前期分析为连接池内存溢出,期间优化了连接池参数,调整了tomcat线程参数,替换数据库连接池,问题依旧    2.看来

【转】Java学习---内存泄露与溢出的区别

Java内存泄露与溢出的区别 Java内存泄漏就是没有及时清理内存垃圾,导致系统无法再给你提供内存资源(内存资源耗尽): 而Java内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出. 内存溢出类似数组越届,超出你能存储的数据的上限 内存泄漏,就是内存使用完毕后,不能释放回收重新使用 Java内存泄露与溢出的区别 内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出. Java内存泄漏就是没有及时清理内存垃圾,导致系统无法再给你提供内存资源(

java中内存泄露和内存溢出

内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出. 内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光. memory leak会最终会导致out of memory! 内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产

JAVA 内存泄露详解(原因、例子及解决)

转载请注明出处:http://blog.csdn.net/anxpp/article/details/51325838,谢谢! Java的一个重要特性就是通过垃圾收集器(GC)自动管理内存的回收,而不需要程序员自己来释放内存.理论上Java中所有不会再被利用的对象所占用的内存,都可以被GC回收,但是Java也存在内存泄露,但它的表现与C++不同. JAVA 中的内存管理 要了解Java中的内存泄露,首先就得知道Java中的内存是如何管理的. 在Java程序中,我们通常使用new为对象分配内存,而

Java内存泄露的理解与解决

Java内存管理机制 在C++语言中,如果需要动态分配一块内存,程序员需要负责这块内存的整个生命周期.从申请分配.到使用.再到最后的释放.这样的过程非常灵活,但是却十分繁琐,程序员很容易由于疏忽而忘记释放内存,从而导致内存的泄露.Java语言对内存管理做了自己的优化,这就是垃圾回收机制.Java的几乎所有内存对象都是在堆内存上分配(基本数据类型除外),然后由GC(garbage collection)负责自动回收不再使用的内存. 上面是Java内存管理机制的基本情况.但是如果仅仅理解到这里,我们