java 中会存在内存泄漏吗 请简单描述。

行业问题 内存,存在 已帮助 人

java 中会存在内存泄漏吗,请简单描述。

热搜:关于java特点描述不正确的是

答案解析

难度★★☆ 搜索
  • 正确答案:

    所谓内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中。java 中有垃圾

    回收机制,它可以保证一对象不再被引用的时候,即对象编程了孤儿的时候,对象将自动被

    垃圾回收器从内存中清除掉。由于Java 使用有向图的方式进行垃圾回收管理,可以消除引

    用循环的问题,例如有两个对象,相互引用,只要它们和根进程不可达的,那么GC 也是可

    以回收它们的,例如下面的代码可以看到这种情况的内存回收:

    package com.huawei.interview;

    import java.io.IOException;

    public class GarbageTest {

    /**

    * @param args

    * @throws IOException

    */

    public static void main(String[] args) throws IOException {

    // TODO Auto-generated method stub

    try {

    gcTest();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    System.out.println("has exited gcTest!");

    System.in.read();

    System.in.read();

    System.out.println("out begin gc!");

    for(int i=0;i<100;i++)

    {

    System.gc();

    System.in.read();

    System.in.read();

    }

    }

    private static void gcTest() throws IOException {

    System.in.read();

    System.in.read();

    Person p1 = new Person();

    System.in.read();

    System.in.read();

    Person p2 = new Person();

    p1.setMate(p2);

    p2.setMate(p1);

    System.out.println("before exit gctest!");

    System.in.read();

    System.in.read();

    System.gc();

    System.out.println("exit gctest!");

    }

    private static class Person

    {

    byte[] data = new byte[20000000];

    Person mate = null;

    public void setMate(Person other)

    {

    mate = other;

    }

    }

    }

    java 中的内存泄露的情况:长生命周期的对象持有短生命周期对象的引用就很可能发生内存

    泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不

    能被回收,这就是java 中内存泄露的发生场景,通俗地说,就是程序员可能创建了一个对

    象,以后一直不再使用这个对象,这个对象却一直被引用,即这个对象无用但是却无法被垃

    圾回收器回收的,这就是java 中可能出现内存泄露的情况,例如,缓存系统,我们加载了

    一个对象放在缓存中(例如放在一个全局map 对象中),然后一直不再使用它,这个对象一直

    被缓存引用,但却不再被使用。

    检查java 中的内存泄露,一定要让程序将各种分支情况都完整执行到程序结束,然后看某

    个对象是否被使用过,如果没有,则才能判定这个对象属于内存泄露。

    下面内容来自于网上(主要特点就是清空堆栈中的某个元素,并不是彻底把它从数组中拿掉,

    而是把存储的总数减少,本人写得可以比这个好,在拿掉某个元素时,顺便也让它从数组中

    消失,将那个元素所在的位置的值设置为null 即可):

    我实在想不到比那个堆栈更经典的例子了,以致于我还要引用别人的例子,下面

    的例子不是我想到的,是书上看到的,当然如果没有在书上看到,可能过一段时

    间我自己也想的到,可是那时我说是我自己想到的也没有人相信的。

    public class Stack {

    private Object[] elements=new Object[10];

    private int size = 0;

    public void push(Object e){

    ensureCapacity();

    elements[size++] = e;

    }

    public Object pop(){

    if( size == 0)

    throw new EmptyStackException();

    return elements[--size];

    }

    private void ensureCapacity(){

    if(elements.length == size){

    Object[] ldElements = elements;

    elements = new Object[2 * elements.length+1];

    System.arraycopy(oldElements,0, elements, 0, size);

    }

    }

    }

    上面的原理应该很简单,假如堆栈加了10 个元素,然后全部弹出来,虽然

    堆栈是空的,没有我们要的东西,但是这是个对象是无法回收的,这个才符合了

    内存泄露的两个条件:无用,无法回收。

    但是就是存在这样的东西也不一定会导致什么样的后果,如果这个堆栈用的

    比较少,也就浪费了几个K 内存而已,反正我们的内存都上G 了,哪里会有什么

    影响,再说这个东西很快就会被回收的,有什么关系。下面看两个例子。

    例子1

    public class Bad{

    public static Stack s=Stack();

    static{

    s.push(new Object());

    s.pop(); //这里有一个对象发生内存泄露

    s.push(new Object()); //上面的对象可以被回收了,等于是自愈了

    }

    }

    因为是static,就一直存在到程序退出,但是我们也可以看到它有自愈功

    能,就是说如果你的Stack 最多有100 个对象,那么最多也就只有100 个对象无

    法被回收其实这个应该很容易理解,Stack 内部持有100 个引用,最坏的情况就

    是他们都是无用的,因为我们一旦放新的进取,以前的引用自然消失!