Java内存泄漏问题

您所在的位置:网站首页 为什么会内存泄漏呢 Java内存泄漏问题

Java内存泄漏问题

2024-06-02 19:20| 来源: 网络整理| 查看: 265

1.什么叫内存泄漏?

简单来说就是一个东西放在内存里的时间太长了,当你的程序都跑完了,它还存在那里。这时它是白白的占用了你的内存,累积起来占用的内存越来越多……最后就会导致JVM报错:out of memory。他占用的是我们的物理内存。

2.java内存泄漏的根本原因是?

内存对象明明已经不需要的时候,还仍然保留着这块内存和它的访问方式(引用)。

3.java既然存在gc线程,为什么还存在内存泄漏?

这个问题,我们需要知道 GC 在什么时候回收内存对象,什么样的内存对象会被 GC 认为是“不再使用”的。

Java中对内存对象的访问,使用的是引用的方式。在 Java 代码中我们维护一个内存对象的引用变量,通过这个引用变量的值,我们可以访问到对应的内存地址中的内存对象空间。在 Java 程序中,这个引用变量本身既可以存放堆内存中,又可以放在代码栈的内存中(与基本数据类型相同)。 GC 线程会从代码栈中的引用变量开始跟踪,从而判定哪些内存是正在使用的。如果 GC 线程通过这种方式,无法跟踪到某一块堆内存,那么 GC 就认为这块内存将不再使用了(因为代码中已经无法访问这块内存了)。

通过这种有向图的内存管理方式,当一个内存对象失去了所有的引用之后,GC 就可以将其回收。反过来说,如果这个对象还存在引用,那么它将不会被 GC 回收,哪怕是 Java 虚拟机抛出 OutOfMemoryError 。

例子1: Vector v = new Vector( 10 ); for ( int i = 1 ;i < 100 ; i ++ ){ Object o = new Object(); v.add(o); o = null ; } 在这个例子中,代码栈中存在Vector 对象的引用 v 和 Object 对象的引用 o 。 在 For 循环中,我们不断的生成新的对象,然后将其添加到 Vector 对象中,之后将 o 引用置空。问题是当 o 引用被置空后, 如果发生 GC , 我们创建的 Object 对象是否能够被 GC 回收呢? 答案是否定的。 因为, GC 在跟踪代码栈中的引用时, 会发现 v 引用,而继续往下跟踪,就会发现 v 引用指向的内存空间中又存在指向 Object 对象的引用。也就是说尽管 o 引用已经被置空, 但是 Object 对象仍然存在其他的引用,是可以被访问到的,所以 GC 无法将其释放掉。 如果在此循环之后, Object 对象对程序已经没有任何作用, 那么我们就认为此 Java 程序发生了内存泄漏。

例子2:

如果想要看到内存溢出,可以按这样的思路去尝试一下:定义一个静态的实例变量(list或其它集合),然后在一个方法里循环往这个静态变量塞东西,直到这个实例变量撑爆你的jvm内存。很快你就能看到out of memory……

import  java.util.ArrayList; import  java.util.List;   public  class  MemoryTest {      private  static  List list =  new  ArrayList();      private  static  int  count =  0 ;            public  static  void  main(String[] args)  throws  InterruptedException {          System.out.println( "申请前的可用内存 = " +getFreeMemory());          while ( true ){               list.add( new  byte [ 1024 * 1024 ]); //用实例变量申请1M内存,当方法执行完毕时,这个static的变量是不会被释放               count++;               if  (count %  100  ==  0 ) {                   System.out.println( "当前list.size()=" +list.size()+ ",可用内存 = " +getFreeMemory());                   Thread.sleep( 500 );               }          }      }            public  static  long  getFreeMemory() {            return  Runtime.getRuntime().freeMemory() / ( 1024  *  1024 );           }   }

所以我们要慎用类变量。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3