这两天看了一本老书《bitter java》,第一次系统地了解了所谓“反模式”。就书的内容来说已经过于陈旧,书中提到的magic servlet、复合jsp等等反模式已经是早就熟知的编程禁忌,而如web页面不能有太多元素这样的反模式也因为ajax的出现(异步加载)变的不是那么“反模式”了,其中又讲述了很多ejb的反模式,这些在轻量级框架流行的今天也早已经过时。不过书中有一个章节倒是挺有价值,讲述的是java的内存泄露问题,我认为是我目前读的关于这方面问题比较有价值的介绍。
网上关于java内存泄露的资料都过于玄乎,其实java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。作者在书中提到了3个场景:
1。流失监听器问题,在awt、swing编程中,给组件添加了事件监听器,这些组件的生命周期如果很长的话,监听器对象将不能被正确回收。关于GUI编程我不是很熟悉,这一点存有疑问,因为显然你触发一个按钮的事件,当然是一直期待同样的行为发生,如果删除了监听器或者使用弱引用让JVM回收不符合业务逻辑和用户体验。
2。集合类,集合类仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。这一点其实也不明确,这个集合类如果仅仅是局部变量,根本不会造成内存泄露,在方法栈退出后就没有引用了会被jvm正常回收。而如果这个集合类是全局性的变量(比如类中的静态属性,全局性的map等),那么没有相应的删除机制,很可能导致集合所占用的内存只增不减,因此提供这样的删除机制或者定期清除策略非常必要。
3。单例模式。不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露,考虑下面的例子:
class A{
public A(){
B.getInstance().setA(this);
}
....
}
//B类采用单例模式
class B{
private A a;
private static B instance=new B();
public B(){}
public static B getInstance(){
return instance;
}
public void setA(A a){
this.a=a;
}
//getter...
}
显然B采用singleton模式,他持有一个A对象的引用,而这个A类的对象将不能被回收。想象下如果A是个比较大的对象或者集合类型会发生什么情况。
上面所讲的这些也启发我们如何去查找内存泄露问题,第一选择当然是利用工具,比如jprofiler,第二就是在代码复审的时候关注长生命周期对象:全局性的集合、单例模式的使用、类的static变量等等。
分享到:
相关推荐
本篇文章将基于“经典之谈——Java内存分配”这一主题,结合“详谈Java的内存分配.pdf”文档,深入讲解Java内存的各个方面。 首先,Java内存分为几个主要区域,分别是:程序计数器(Program Counter Register)、...
对于防止Java内存泄漏,以下是一些实践建议: 1. 避免在静态字段中存储大量数据或引用。 2. 使用完对象后,及时将其引用设为null,特别是在集合类中。 3. 注意单例模式的实现,确保单例对象在不再使用时能够被垃圾...
内存泄漏是C/C++编程中一个严重的问题,它指的是程序在申请内存后,无法释放不再使用的内存空间。本文主要探讨了两种主要的解决方案——Smart Pointer和Garbage Collection,以及内存泄漏的检测工具。 首先,Smart ...
Java内存泄露通常涉及对象生命周期和垃圾回收机制。当一个对象不再被任何引用所指向,理论上它应该被垃圾回收器回收。但若长生命周期的对象持有短生命周期对象的引用,即使短生命周期对象已完成其使命,由于引用的...
Java的自动垃圾回收机制也是一个显著优点,它减轻了程序员管理内存的负担,降低了程序出现内存泄漏的风险。此外,自JDK 1.5以来,Java的性能不断提升,使得Java在处理大量数据和高并发场景时表现优秀,甚至有人提出...
Java 垃圾回收机制是 Java 语言中的一种自动内存管理机制,它可以自动回收内存中的垃圾,避免代码运行时由于忘记释放对象而带来的内存泄漏问题。 Java 中的垃圾回收机制主要通过两种算法来判断对象是否可以被回收,...
### 浅谈Java语言评价胜出的8大技术优势 #### 1. 强大的API支持 Java提供了非常丰富的API支持,包括网络编程中的Socket API、数据库操作中的SQL API、图形用户界面的Swing和AWT API等。这些API不仅功能强大而且...
Java内存管理是Java虚拟机(JVM)的关键组成部分,它主要负责对象的创建、分配、初始化以及回收。本文将深入探讨Java内存管理的原理以及内存溢出异常的原因和解决策略。 首先,Java与C/C++在内存管理上的一个重要...
### Java分布式应用学习笔记02再谈JVM 在深入探讨Java虚拟机(JVM)时,我们再次聚焦于这个核心组件,它不仅是Java运行环境的心脏,也是构建分布式应用的关键技术之一。JVM作为Java语言的核心执行环境,其设计与...
浅谈Java堆外内存之突破JVM枷锁 本文主要介绍了Java堆外内存的概念,包括JVM内存分配、JVM垃圾回收、堆外内存的垃圾回收等相关内容。Java开发者都知道,Java中不需要手动申请和释放内存,JVM会自动进行垃圾回收;而...
Java内存分配机制是Java编程中不...理解Java内存分配和变量存储位置对于优化代码、避免内存泄漏和理解垃圾回收机制至关重要。开发者应当根据变量的生命周期和使用场景,合理选择存储位置,以达到高效、安全的内存管理。
浅谈Java技术对互联网时代的重要作用 Java技术是互联网时代不可或缺的一部分,自从1996年初Sun公司发布第一个Java开发工具以来,Java语言就成为了跨平台的、面向对象的编程语言。Java语言的优良特性,如可移植性、...
- 连接未正确关闭可能导致内存泄漏。 - 连接数量无法有效控制,可能引发服务器崩溃。 **数据库连接池的工作原理** 为解决这些问题,引入了数据库连接池。连接池管理数据库连接,就像一个预分配的资源池,应用程序...
4. **无用单元收集堆(Garbage-collected heap)**:Java对象在堆内存中分配,JVM负责自动管理内存,包括对象的创建和销毁,通过无用单元收集(Garbage Collection)机制来回收不再使用的内存,避免内存泄露。...
正确地管理和使用变量,可以提高程序的性能,减少内存泄漏,确保程序的稳定性和安全性。在编程实践中,应遵循良好的变量命名规范,合理控制变量的作用域,注意变量的初始化和生存期,以及理解不同类型变量在内存中的...
资料中的“浅谈内存泄漏”系列详细分析了内存泄漏的原因和检测方法。 5. 垃圾回收:在某些高级语言(如Java、Python)中,垃圾回收机制自动回收不再使用的内存,避免内存泄漏。但这也会引入额外的性能开销。 6. ...