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

news/2024/7/20 13:22:33 标签: java, 内存管理

内存泄露是指系统中存在无法回收的内存,有时候会造成内存不足或系统崩溃。

虽然Java存在内存泄露,但是基本上不用很关心它,非凡是那些对代码本身就不讲究的就更不要去关心这个了。Java中的内存泄露当然是指:存在无用但是垃圾回收器无法回收的对象。而且即使有内存泄露问题存在,也不一定会表现出来。

Java是如何管理内存

 
  为了判断Java中是否有内存泄露,我们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中,程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外),所有的对象都在堆 (Heap)中分配空间。另外,对象的释放是由GC决定和执行的。在Java中,内存的分配是由程序完成的,而内存的释放是有GC完成的,这种收支两条线的方法确实简化了程序员的工作。但同时,它也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。因为,GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。
 
  监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。
 
  为了更好理解GC的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从main进程开始执行,那么该图就是以main进程顶点开始的一棵根树。在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。
 
  以下,我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况。以下右图,就是左边程序运行到第6行的示意图。
 
  
 
  Java使用有向图的方式进行内存管理,可以消除引用循环的问题,例如有三个对象,相互引用,只要它们和根进程不可达的,那么GC也是可以回收它们的。这种方式的优点是管理内存的精度很高,但是效率较低。另外一种常用的内存管理技术是使用计数器,例如COM模型采用计数器方式管理构件,它与有向图相比,精度行低(很难处理循环引用的问题),但执行效率很高。
 
  Java内存泄露情况
 
  JVM回收算法是很复杂的,我也不知道他们怎么实现的,但是我只知道他们要实现的就是:对于没有被引用的对象是可以回收的。所以你要造成内存泄露就要做到:
 
  持有对无用对象的引用!
 
  不要以为这个很轻易做到,既然无用,你怎么还会持有它的引用? 既然你还持有它,它怎么会是无用的呢?
 
http://www.lijingquan.net/java-memleak.html

 

会。java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。

    1.集合类,集合类仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。这一点其实也不明确,这个集合类如果仅仅是局部变量,根本不会造成内存泄露,在方法栈退出后就没有引用了会被jvm正常回收。而如果这个集合类是全局性的变量(比如类中的静态属性,全局性的map等即有静态引用或final一直指向它),那么没有相应的删除机制,很可能导致集合所占用的内存只增不减,因此提供这样的删除机制或者定期清除策略非常必要。

   2.单例模式。不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在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是个比较大的对象或者集合类型会发生什么情况。

   上面所讲的这些也启发我们如何去查找内存泄露问题,在代码复审的时候关注长生命周期对象:全局性的集合、单例模式的使用、类的static变量等等。在Java的实现过程中,也要考虑其对象释放,最好的方法是在不使用某对象时,显式地将此对象赋空。最好遵循谁创建谁释放的原则。

转载于:https://www.cnblogs.com/WayneZeng/archive/2013/04/03/2997164.html


http://www.niftyadmin.cn/n/937406.html

相关文章

数据库表中状态:1表示开启,0表示关闭。

1.数据表中。 关于状态的字段,只有 一个Int类型的字段,比如下方: 2.domain的JavaBean. 关于状态就有两个字段,一个String型,一个Integer型。 比如下方这个: 3.dao层 01.插入数据根据数据库表的字段。 02…

设计模式 之 《代理模式》

#ifndef __PROXY_MODEL_H__ #define __PROXY_MODEL_H__#include <iostream> using namespace std;class Subject {virtual void request() 0; };class RealSubject : public Subject { public:void request(){ cout<<"真实的请求&#xff01;"<<e…

排:快速排序

思路&#xff1a;分为交换和递归。 交换&#xff1a; 从右往左&#xff1a;如果值>当前值&#xff0c;则跳过 从左往右&#xff1a;如果值<当前值&#xff0c;则跳过 基准数: int temp arr[left]; 递归&#xff1a; 方法&#xff1a; quickSort(arr,left,i-1); quickSort…

centos的用户、组权限、添加删除用户等操作的详细操作命令

1.Linux操作系统是多用户多任务操作系统&#xff0c;包括用户账户和组账户两种 细分用户账户&#xff08;普通用户账户&#xff0c;超级用户账户&#xff09;除了用户账户以为还 有组账户所谓组账户就是用户账户的集合&#xff0c;centos组中有两种类型&#xff0c;私有组和标准…

视频点播服务器构建(转载)

摘要&#xff1a;LiveMedia已经在VLC和MPlayer等开源的流媒体播放软件中得到应用。文章对LiveMedia的组成和功能进行了分析&#xff0c;并对LiveMedia在视频点播方面的应用进行了详细的阐述。  关键词&#xff1a;流媒体RTPRTSP服务器视频点播     流媒体的市场空间迅速扩…

1.数据库练习limit

数据库表 CREATE TABLE employees ( emp_no INT(11) NOT NULL, birth_date DATE NOT NULL, first_name VARCHAR(14) NOT NULL, last_name VARCHAR(16) NOT NULL, gender CHAR(1) NOT NULL, hire_date DATE NOT NULL, PRIMARY KEY (emp_no));插入数据 INSERT INTO employees V…

在线考试系统随记1

再次着手做在线考试系统的第一天.用到Oracle11GR2数据库、Tomcat6.0、Hibernate、Struts2.之前用的是mysql数据库&#xff0c;这次直接把建表语句拿来用了,在bit上的时候遇见了问题.提示“ORA-00902: 无效数据类型”。把建表语句中的"bit"改成了"numeric(1,0)&q…

Java50道编程题

题目5&#xff1a;利用条件运算符的嵌套来完成此题&#xff1a;学习成绩> 90分的同学用A表示&#xff0c;60-89分之间的用B表示&#xff0c;60分以下的用C表示。 public class Solution {public static void main(String[] args) {Scanner sc new Scanner(System.in);Syst…