内存泄漏是指本应释放的内存没有及时释放,被某个或某些实例持有但不再使用,导致GC无法回收。Java内存分配策略Java程序运行时的内存分配策略分为三种,分别是静态分配、栈分配和堆分配。对应的三种策略使用的内存空间分别是静态存储区(也叫方法区)、栈区、堆区。静态存储区(方法区):主要存放静态数据、全局静态数据和常量。这块内存是在程序编译时分配的,并在整个程序运行时都存在。栈区:方法执行时,方法内部的局部变量都是在栈内存中创建的,分配的内存在方法结束后自动释放。因为栈内存分配在处理器的指令集中,效率很高,但分配的内存容量有限。堆区:又称动态内存分配,通常是指程序运行时直接new的内存。这部分内存在不适用的时候会被Java垃圾回收器回收。栈和堆的区别:方法体中定义的一些基本类型的变量和对象引用变量(局部变量)是在方法的栈内存中分配的。当在方法块中定义变量时,Java会在栈上为其分配内存。当超出变量的作用域时,变量将失效。这时候占用的内存就会被释放,然后重新使用。.堆内存用于存放所有新对象(包括对象中的所有成员变量)和数组。堆上分配的内存由Java垃圾回收管理器自动管理。要在堆中创建一个对象或数组,可以在栈中定义一个特殊的变量。该变量的值等于数组或对象在堆内存中的首地址。这个特殊变量就是我们上面提到的引用变量。我们可以通过引用变量来访问堆内存中的对象或数组。例如:publicclassSample{ints1=0;SamplemSample1=newSample();publicvoidmethod(){ints2=0;SamplemSample2=newSample();}}SamplemSample3=newSample();上面的局部变量s2和mSample2存放在栈内存中,mSample3指向的对象存放在堆内存中,包括对象的成员变量s1和mSample1也存放在堆中,而自身存放在堆内存中堆。结论:局部变量的基本类型和引用存放在栈内存中,引用的实体存放在堆中。——因为它们存在于方法中,所以随着方法的生命周期结束。成员变量全部存储在堆中(包括基本数据类型、引用和被引用的对象实体)。——因为属于类,所以类对象最终会被new使用。了解了Java的内存分配之后,我们再来看看Java是如何管理内存的。Java如何管理内存程序分配内存,GC释放。内存释放的原则是对象或数组不再被引用,JVM会在合适的时候回收内存。内存管理算法:1.引用计数法:引用变量定义在对象内部。当对象被引用变量引用时,计数加1。当对象的引用变量超过生命周期或引用新变量时,计数减1。任何引用计数为0的对象实例可以进行GC。这种算法的优点是引用计数收集器可以执行得非常快,并且穿插在程序的运行中。更有利于程序不需要长时间中断的实时环境。缺点:无法检测到循环引用。引用计数无法解决的循环引用问题如下:publicvoidmethod(){//Samplecount=1Sampleob1=newSample();//Samplecount=2Sampleob2=newSample();//Samplecount=3ob1.mSample=ob2;//样本数=4ob2。mSample=ob1;//Samplecount=3ob1=null;//Samplecount=2ob2=null;//count为2,不能GC}Java可以作为GCROOT的对象有:虚拟机栈中引用的对象(局部变量table),方法区静态属性引用的对象,方法区常量引用的对象,本地方法栈(Nativeobjects)引用的对象2.标记和清除方法:从根节点集合开始扫描,标记存活的对象,然后扫描整个空间以回收未标记的对象。在很多存活对象的情况下,效率很高,但是会造成内存碎片。3、标记和排序算法:同mark和clear方法,只是在回收对象时将存活的对象移走。虽然解决了内存碎片的问题,但是增加了内存的开销。4.复制算法:这种方法是为了克服句柄的开销,解决堆碎片。将堆分成一个对象平面和多个自由平面。将存活的物体复制到自由表面,主自由表面成为物体表面,原物体表面成为自由表面。这会增加内存开销,并且程序会在交换期间暂停执行。5.分代算法:分代垃圾回收策略是基于不同的对象有不同的生命周期。因此,不同生命周期的对象可以采用不同的回收算法来提高回收效率。年轻代:1.所有新生成的对象首先存放在年轻代中。年轻一代的目标是尽快收集那些短命的对象。2、新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区。一个伊甸区,两个幸存者区(一般来说)。大多数对象生成在伊甸园区域。回收时,先将eden区存活的对象复制到一个survivor0区,然后清除eden区。当survivor0区也满了,将eden区和survivor0区的存活对象复制到另一个survivor1区,然后清除eden区和这个区。survivor0区,此时survivor0区为空,然后survivor0区和survivor1区交换,即survivor1区保持为空,以此类推。3、当survivor1区域不足以存放eden和survivor0的存活对象时,直接将存活对象存放到老年代。如果老年代也满了,就会触发FullGC,即新生代和老年代都会被回收。4.新生代发生的GC也称为MinorGC。)老年代:1.在新生代中存活N次垃圾回收的对象将被放入老年代。因此,可以认为老年代存储的所有对象都是长生命周期的对象。2.内存比新生代大很多(大概1:2)。当老年代内存满了,就会触发MajorGC,即FullGC。FullGC的频率比较低,对象在老年代的存活时间比较长,存活率标记高。持久代:用于存放静态文件,如Java类、方法等。持久代对垃圾回收没有太大影响,但有些应用可能会动态生成或调用一些类,如Hibernate等。此时,运行时需要设置一个比较大的永久代空间来存放这些新加入的类。Android常见内存泄漏汇总集合类泄漏先看一段代码List