非常多人有疑问,java有非常好的垃圾回收机制,怎么会有内存泄露?事实上是有的,那么何为内存泄露?在Java中所谓内存泄露就是指在程序执行的过程中产生了一些对象,当不须要这些对象时,他们却没有被垃圾回收掉,并且程序执行中非常难发现这个对象。它始终占领着内存却没有发挥作用。

我举这样一个样例,在现实开发中我们须要自己定义一个先进后出的栈集合,代码例如以下:

package cn.lmj.demo2;

import java.util.ArrayList;
import java.util.List; public class MyStack
{
private List list = new ArrayList();
private int len = 0;
public void put(T obj)
{
list.add(obj);
len++;
} public T pop()
{
int index = --len;
return list.get(index);
} }

这个代码看起来和执行起来都没问题,可是,这里有个非常隐晦的问题,就是在pop()方法里面。我们首先找到集合最后一个元素的下标。然后依照下标从集合中取出,可是这个对象真的从集合中移走了吗?答案不是的,也就是说你取出来的对象看似从栈中取出来了。可是它却还存在于集合中占领着内存。并且你非常难发现它,这就产生了内存泄露,正确的pop()方法应该是

public T pop()
{
int index = --len;
return list.remove(index);   //取出的同一时候删除集合中的元素
}

在java中,还有这样一个场景也会出现内存泄露问题,并且也是非常隐晦的,我们在用Map存一对键值型的数据时。我们假设存进去了,那么就不要改动Map的key值參与计算的hashCode方法和equals方法,例如以下代码就有内存泄露问题:

package cn.lmj.demo2;

import java.util.HashMap;
import java.util.Map; public class Demo03
{
public static void main(String[] args)
{
Map map = new HashMap();
Person p1 = new Person("aaa");
Person p2 = new Person("bbb");
Person p3 = new Person("ccc");
map.put(p1,"1");
map.put(p2,"2");
map.put(p3,"3");
System.out.println(map.containsKey(new Person("aaa")));//true
p1.setName("eee"); //改变參与计算的hashCode和equals值
System.out.println(map.containsKey(new Person("aaa")));//false
}
} class Person
{
private String name; public Person(String name)
{
super();
this.name = name;
} public Person()
{
super();
} //利用name属性生成hashCode和equals方法
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
} @Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (name == null)
{
if (other.name != null)
return false;
}
else if (!name.equals(other.name))
return false;
return true;
} public String getName()
{
return name;
} public void setName(String name)
{
this.name = name;
} }

总结:

在java中是有内存泄露的情况。那么我们在开发中怎样避免内存泄露?除了上面两种情况的以外:

1、最主要的建议是尽早释放无用对象的引用。如:
  …..

  A a = new A()。

  //应用a对象

  a = null。 //当使用对象a之后主动将其设置为空
  …

  注:假设a 是方法的返回值,不要做这种处理。否则你从该方法中得到的返回值永远为空,并且这种错误不易被发现、排除

  2、尽量少用finalize函数。它会加大GC的工作量。

  3、假设须要使用经经常使用到的图片。能够使用soft应用类型。

它尽可能把图片保存在内存中

  4、注意集合数据类型,包含数组、树、图、链表等数据结构,这些数据结构对GC来说。回收更为复杂。

  5、尽量避免在类的默认构造器中创建、初始化大量的对象,防止在调用其自类的构造器时造成不必要的内存资源浪费

  6、尽量避免强制系统做垃圾内存的回收。增长系统做垃圾回收的终于时间

  7、尽量避免显式申请数组空间

  8、尽量做远程方法调用类应用开发时使用瞬间值变量。除非远程调用端须要获取该瞬间值变量的值。

  9、尽量在合适的场景下使用对象池技术以提高系统性能。

java内存泄露具体解释的更多相关文章

  1. Java内存泄露监控工具:JVM监控工具介绍【转】

    jstack?-- 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程 ...

  2. 关于java内存泄露的总结--引用的类型:强引用,弱引用,软引用

    今天面试了一家公司的java开发方面的实习生,被问到一个问题:如何处理java中的内存泄露问题,保证java的虚拟机内存不会被爆掉,当时其实觉得面试官的问题有点泛,所以也没有很好领会他的意思,答案也不 ...

  3. java内存泄露的理解与解决(转)

    Java内存管理机制 在C++语言中,如果需要动态分配一块内存,程序员需要负责这块内存的整个生命周期.从申请分配.到使用.再到最后的释放.这样的过程非常灵活,但是却十分繁琐,程序员很容易由于疏忽而忘记 ...

  4. Java内存泄露的原因

    Java内存泄露的原因 1.静态集合类像HashMap.Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,所有的对象Object也不能被释放,因为他们也将一直被Vector ...

  5. Java 内存泄露

    一.Java内存回收机制 不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址.Java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆(Hea ...

  6. Java 内存泄露的理解与解决过程

    本文详细地介绍了Java内存管理的原理,以及内存泄露产生的原因,同时提供了一些列解决Java内存泄露的方案,希望对各位Java开发者有所帮助. Java内存管理机制 在C++ 语言中,如果需要动态分配 ...

  7. Java内存泄露原因详解

    一.Java内存回收机制 不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址.Java中对象是采用new或者反射的方法创建的, 这些对象的创建都是在堆(He ...

  8. java内存泄露与内存溢出

    内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory: 内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空 ...

  9. [译]Java内存泄露介绍

    (本文章翻译自the-introduction-of-memory-leak-what-why-and-how) Java最大的优势之一就是它的内存管理机制.你可以简单创建对象然后垃圾回收器会负责分配 ...

随机推荐

  1. Yii初学者必看(转载)

    Active Record (AR) 是一个流行的 对象-关系映射 (ORM) 技术. 每个 AR 类代表一个数据表(或视图),数据表(或视图)的列在 AR 类中体现为类的属性,一个 AR 实例则表示 ...

  2. OpenOPC

    客户端连接OpenOPC Gateway import OpenOPC gateway='192.168.1.90' opchost='testbox' opcserv='KEPware.KEPSer ...

  3. HDU - 3664 Permutation Counting

    Discription Given a permutation a1, a2, … aN of {1, 2, …, N}, we define its E-value as the amount of ...

  4. 【webpack2】-- 入门与解析

    每次学新东西总感觉自己是不是变笨了,看了几个博客,试着试着就跑不下去,无奈只有去看官方文档. webpack是基于node的.先安装最新的node. 1.初始化 安装node后,新建一个目录,比如ht ...

  5. 椭圆人头跟踪bmp图像序列 BMP Image Sequences for Elliptical Head Tracking

    BMP Image Sequences for Elliptical Head Tracking The BMP image sequences used in the head tracking d ...

  6. 彻底搞懂oracle的标量子查询

    oracle标量子查询和自己定义函数有时用起来比較方便,并且开发者也常常使用.数据量小还无所谓.数据量大,往往存在性能问题. 下面測试帮助大家彻底搞懂标量子查询. SQL> create tab ...

  7. uva 11248 Frequency Hopping (最大流)

    uva 11248 Frequency Hopping 题目大意:给定一个有向网络,每条边均有一个容量. 问是否存在一个从点1到点N.流量为C的流.假设不存在,能否够恰好改动一条弧的容量,使得存在这种 ...

  8. 设计模式之中介者模式(Mediator)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程.它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  9. .net 反射访问私有变量和私有方法 如何创建C# Closure ? C# 批量生成随机密码,必须包含数字和字母,并用加密算法加密 C#中的foreach和yield 数组为什么可以使用linq查询 C#中的 具名参数 和 可选参数 显示实现接口 异步CTP(Async CTP)为什么那样工作? C#多线程基础,适合新手了解 C#加快Bitmap的访问速度 C#实现对图片文件的压

    以下为本次实践代码: using System; using System.Collections.Generic; using System.ComponentModel; using System ...

  10. 日志打印longging模块(控制台和文件同时输出)

    在把日志写入文件的同时在控制台输出 示例代码如下: #coding=utf-8 import logging import time import os dir = os.path.dirname(o ...