Java内存泄漏
来源:互联网 发布:ppt课件下载软件 编辑:程序博客网 时间:2024/06/11 05:58
Java内存回收方式
Java判断对象是否可以回收使用的而是可达性分析算法。
在主流的商用程序语言中(Java和C#),都是使用可达性分析算法判断对象是否存活的。这个算法的基本思路就是通过一系列名为”GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,下图对象object5, object6, object7虽然有互相判断,但它们到GC Roots是不可达的,所以它们将会判定为是可回收对象。
在Java语言里,可作为GC Roots对象的包括如下几种(摘自《深入理解Java虚拟机》):
*虚拟机栈(栈桢中的本地变量表)中的引用的对象
*方法区中的类静态属性引用的对象
*方法区中的常量引用的对象
*本地方法栈中JNI的引用的对象
*方法区中的类静态属性引用的对象
*方法区中的常量引用的对象
*本地方法栈中JNI的引用的对象
内存泄漏的情形
因为静态成员保存在静态存储区,垃圾回收时不进行回收,只有在程序结束时才会被回收,
所以静态成员的生命期和程序的生命期一样长。在垃圾回收时,若本该被回收的部分持有静态成员的引用
则该部分就不会被回收,这种情况多次发生会导致内存不足从而导致内存泄漏。
****************************************************************************************************************
***以下内容有点乱,仅供参考***
1.静态成员引起的泄漏
public class TestActivity extends Activity { private static Context sContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); sContext = this; RefWatcher refWatcher = App.getRefWatcher(this); refWatcher.watch(this);// 监控的对象 }}
分析:声明static后,sContext的生命周期将和Application一样长,Activity即使退出到桌面,Application依然存在->sContext依然存在,GC此时想回收Activity却发现Activity仍然被sContext(GC-ROOT连接着),导致回收不了,内存泄露。
2.单例模式引起的泄漏
public class DownloadManager { private static DownloadManager instance; private Task task ; public static DownloadManager getInstance(){ if (instance == null) { instance = new DownloadManager(); } return instance; } public Task newTask(){ this.task = new Task(); return task; }}public class Task { private Call call; public Call newCall(){ this.call = new Call(); return call; }}public class Call { public void execute(){ System.out.println("=========> execute call"); }}
Test
public class TestActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); RefWatcher refWatcher = App.getRefWatcher(this); Task task = DownloadManager.getInstance().newTask(); Call call = task.newCall(); call.execute(); refWatcher.watch(call);// 监控的对象 call = null; // 无法回收,DownloadManager是静态单例,引用task,task引用了call,即使call置为空,也无法回收,切断GC_ROOT 联系即可避免内存泄露,即置task为空。 }}
补充Android相关:
如果某些单例需要使用到Context对象,推荐使用Application的context,不要使用Activity的context,否则容易导致内存泄露。单例对象的生命周期和Application一致,这样Application和单例对象就一起销毁。
如果某些单例需要使用到Context对象,推荐使用Application的context,不要使用Activity的context,否则容易导致内存泄露。单例对象的生命周期和Application一致,这样Application和单例对象就一起销毁。
3.内部类引起的泄漏
因为静态内部类不持有外部类的引用,而非静态内部类持有外部类的引用。若在外部类定义了一个非静态内部类的静态属性,即使令内部类为null,也无法回收内部类,导致内存泄漏。
public class OutterClass { private static Inner inner; class Inner{ public void list(){ System.out.println("outter name is " + name); } }}
所以优先使用静态内部类而不是非静态的,因为非静态内部类持有外部类引用可能导致垃圾回收失败。
补充Android相关:
如果你的静态内部类需要宿主Activity的引用来执行某些东西,你要将这个引用封装在一个WeakReference中,避免意外导致Activity泄露,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收 只被弱引用关联 的对象,只被 说明这个对象本身已经没有用处了。
*********************************************************************************************************************************
(来自编程之乐)
阅读全文
0 0
- Java的内存泄漏
- Java的内存泄漏
- Java的内存泄漏
- java 内存泄漏
- java内存泄漏
- Java的内存泄漏
- Java的内存泄漏
- Java的内存泄漏
- Java的内存泄漏
- Java的内存泄漏
- Java的内存泄漏
- Java的内存泄漏
- Java的内存泄漏
- java内存泄漏
- Java的内存泄漏
- Java内存泄漏问题
- Java的内存泄漏
- Java的内存泄漏
- 机器学习_直线/平面的函数形式
- 第八周 项目2 数据结构之自建算法库——链串
- Photoshop常用快捷键
- 棋类AI相关
- 线程之间的协作
- Java内存泄漏
- XAMPP 更改项目路径任意位置且不影响htdocs内的文件访问
- java中native解释
- gradle 命令打包
- 阿里云centos7安装IonCube的方法详解教程
- 【干货】MySQL和pymysql最基本扫盲~带你上路~
- perMnently added the ecdsa host key for ip address ‘【ip地址】’ to the list of known hosts
- 软件工程概论知识总结
- 记一次SYSAUX表空间坏块处理