Java内存泄露原因详解

Java内存泄露原因详解虽然 Java 有 JVM 帮助管理内存 但还是会发生内存泄露的情况 以下将对 Java 内存泄露的各种情况进行分析

一、Java内存回收机制

不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址。Java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆(Heap)中分配的,所有对象的回收都是由Java虚拟机通过垃圾回收机制完成的。GC为了能够正确释放对象,会监控每个对象的运行状况,对他们的申请、引用、被引用、赋值等状况进行监控,Java会使用有向图的方法进行管理内存,实时监控对象是否可以达到,如果不可到达,则就将其回收,这样也可以消除引用循环的问题。在Java语言中,判断一个内存空间是否符合垃圾收集标准有两个:一个是给对象赋予了空值null,以下再没有调用过,另一个是给对象赋予了新值,这样重新分配了内存空间。

二、Java内存泄露引起原因

1、静态集合类引起内存泄露:

Static Vector v = new Vector(10); for (int i = 1; i<100; i++) { Object o = new Object(); v.add(o); o = null; }

在这个例子中,循环申请Object 对象,并将所申请的对象放入一个Vector 中,如果仅仅释放引用本身(o=null),那么Vector 仍然引用该对象,所以这个对象对GC 来说是不可回收的。因此,如果对象加入到Vector 后,还必须从Vector 中删除,最简单的方法就是将Vector对象设置为null。

2、当集合里面的对象属性被修改后,再调用remove()方法时不起作用。

例:

public static void main(String[] args) { Set 
  
    set = 
   new HashSet 
   
     (); Person p1 = 
    new Person( 
    "唐僧", 
    "pwd1", 
    25); Person p2 = 
    new Person( 
    "孙悟空", 
    "pwd2", 
    26); Person p3 = 
    new Person( 
    "猪八戒", 
    "pwd3", 
    27); set.add(p1); set.add(p2); set.add(p3); System.out.println( 
    "总共有:"+set.size()+ 
    " 个元素!"); 
    //结果:总共有:3 个元素!  p3.setAge( 
    2); 
    //修改p3的年龄,此时p3元素对应的hashcode值发生改变  set.remove(p3); 
    //此时remove不掉,造成内存泄漏 set.add(p3); 
    //重新添加,居然添加成功  System.out.println( 
    "总共有:"+set.size()+ 
    " 个元素!"); 
    //结果:总共有:4 个元素!  
    for (Person person : set) { System.out.println(person); } } 
    
  

3、监听器

在java 编程中,我们都需要和监听器打交道,通常一个应用当中会用到很多监听器,我们会调用一个控件的诸如addXXXListener()等方法来增加监听器,但往往在释放对象的时候却没有记住去删除这些监听器,从而增加了内存泄漏的机会。

4、各种连接

比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,除非其显式的调用了其close()方法将其连接关闭,否则是不会自动被GC 回收的。对于Resultset 和Statement 对象可以不进行显式回收,但Connection 一定要显式回收,因为Connection 在任何时候都无法自动回收,而Connection一旦回收,Resultset 和Statement 对象就会立即为NULL。但是如果使用连接池,情况就不一样了,除了要显式地关闭连接,还必须显式地关闭Resultset Statement 对象(关闭其中一个,另外一个也会关闭),否则就会造成大量的Statement 对象无法释放,从而引起内存泄漏。这种情况下一般都会在try里面去的连接,在finally里面释放连接。

5、内部类和外部模块等的引用

6、单例模式

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/223316.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午2:21
下一篇 2026年3月17日 下午2:22


相关推荐

  • Pubmedy加载时显示程序包无效的解决方案[通俗易懂]

    目前谷歌应用商城已经下架Pubmedy,本地安装又遇到程序包无效:“CRX_HEADER_INVALID”。解决方案:将PubMedy.crx重命名为PubMedy.rar解压到要安装的位置找到扩展程序选项,并启用开发者选项选择加载已解压的扩展程序5.选择解压目录可以看到已经安装完毕…

    2022年4月9日
    98
  • Kimi 浏览器插件来了,配置只需要 1 分钟!

    Kimi 浏览器插件来了,配置只需要 1 分钟!

    2026年3月12日
    2
  • 女生适合做java程序员吗?

    女生适合做java程序员吗?一提到程序员 大部分人脑中的画面就是男生坐在电脑前敲代码 似乎女生和程序员完全不沾边 那女生可不可以做程序员呢 随着 IT 行业的飞速发展 程序员越来越受到重视 是所谓的有一技之长的人 越来越多的女生也想加入到程序员的行列 但她们都存在各种各样的疑问和顾虑 比如女生学编程 做程序员好吗 女生做程序员有前途吗 女生学程序员的利弊都有哪些呢 女生学 java 好吗 女生做程序员经常加班 会不会老的快呢 女

    2026年2月17日
    2
  • 如何成为运维架构师

    如何成为运维架构师在百度里搜索运维架构师,你会发现招聘的职位还不少并且月薪、年薪都很可观。提到架构师,大家都觉得挺神秘的,而作为运维领域的架构师,站在系统稳定和高可用、高扩展的角度,其承载着太多的责任和挑战。对于运维工程师来说,运维架构师就像是一个目标抑或是一座山峰。如何成为一名优秀的运维架构师?运维架构师应该具备何种职业素质?需要什么样的知识体系呢?一、职业素质运维架构师一词应该是与系统架构师、软件架构师、网络架构师、业务架构师不同的,虽然都是架构师,但侧重不同。在一个企业的IT系统中,运维架构师更需要具…

    2022年7月17日
    14
  • 计算机语言cobol,COBOL语言编译器

    计算机语言cobol,COBOL语言编译器COBOL 语言 是一种面向过程的高级程序设计语言 主要用于数据处理 是国际上应用最广泛的一种高级语言 COBOL 是英文 CommonBusine OrientedLang 的缩写 原意是面向商业的通用语言 COBOL 语言编译器是指将 COBOL 源代码编译转换成机器代码的编译器 编译器首先检查是否有任何语法错误 然后将其转换为机器语言 编译器创建一个称为加载模块输出文件 此输出文件包含 0 和

    2026年3月18日
    2
  • android r文件丢失_读取文件

    android r文件丢失_读取文件在用Eclipse做开发的时候,总是无缘无故缺少R文件,让整个项目报废,在网上查了资料后现在做一下整理。1、右击你的Android项目——>AndroidTools——>FixProjectProperties即可。2、清理下项目:使用菜单Project——>clean——>选中需要clean的项目这个最简单的方法,但是我觉得这并没有什么卵用。。。。。

    2022年10月4日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号