我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java应用程序中内存泄漏及内存管理的示例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java应用程序中内存泄漏及内存管理的示例分析

这篇文章主要介绍Java应用程序中内存泄漏及内存管理的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

btw,一些静态代码扫描工具也能检测出不好的编程习惯带来潜在的内存泄露的风险。

Java平台的一个突出的特性是自动内存管理。很多人把这种特性误读为Java没有内存泄露。然而,在我印象中,现代Java框架以及基于Java的平台并非如此。特别是Android平台,能举出很多反例。为了让大家对Java平台的内存泄露有一个初步的认识,我们先来看一个Java实现的栈:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

classSimpleStack {

 

    privatefinalObject[] objectPool =newObject[10];

    privateintpointer = -1;

 

    publicObject pop() {

        if(pointer <0) {

            thrownewIllegalStateException("no elements on stack");

        }

        returnobjectPool[pointer--];

    }

 

    publicObject peek() {

        if(pointer <0) {

            thrownewIllegalStateException("no elements on stack");

        }

        returnobjectPool[pointer];

 

    }

 

    publicvoidpush(Object object) {

        if(pointer >8) {

            thrownewIllegalStateException("stack overflow");

        }

        objectPool[++pointer] = object;

    }

}

这个栈的实现基于一个对象数组,并维护了一个用于指向栈内当前可用单元的整型指针。上面的实现中,每次从栈顶弹出元素都会产生内存泄露。确切的说,即使不再使用栈顶元素,对象数组会继续持有栈顶元素的引用(除非栈顶元素再次入栈,栈顶元素的引用会被完全相同的引用覆盖)。因此,即便这个对象的其他引用都被释放,Java虚拟机也不能回收这个对象。由于这种栈实现并不允许外界直接访问其底层的对象池,因此除非有新元素入栈并被放置在栈内的同一个位置上,否则这个无法访问的引用将阻止垃圾回收器回收该对象。

幸运的是,这个内存泄露很容易修复:

1

2

3

4

5

6

7

8

9

10

publicObject pop() {

    if(pointer <1) {

        thrownewIllegalStateException("no elements on stack");

    }

    try{

        returnobjectPool[pointer];

    }finally{

        objectPool[pointer--] =null;

    }

}

当然,在日常的Java开发中一般不会去实现一个内存数据结构。因此,让我们来看一个更常见的Java内存泄漏的例子。在Java开发中经常用到的观察者模式就会引起内存泄露:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

classObserved {

 

    publicinterfaceObserver {

        voidupdate();

    }

 

    privateCollection<Observer> observers =newHashSet<Observer>();

 

    voidaddListener(Observer observer) {

        observers.add(observer);

    }

 

    voidremoveListener(Observer observer) {

        observers.remove(observer);

    }

 

}

这次提供了一个直接删除底层对象池引用的方法。基于这种实现,任何已注册的Observer在使用后只要被正确注销,就不会存在内存泄漏的风险。然而,假设这样一个场景,框架的使用者在使用完Observer之后并没有及时注销。同理Observer将永远不会被回收,因为Observed一直保留着它的引用。更糟的是,没有Observer引用,是无法从Observed对象池外部删除Observer的,即无法回收未被及时注销的Observer。

不过,有一种简单的方法能够修复这种潜在的内存泄露——弱引用。我个人认为这是Java程序员都应该知道的特性。简单地说,弱引用在功能上和普通的引用一样,但它不会妨碍垃圾回收。因此JVM执行垃圾回收时,如果没有发现强引用,那么你就会发现弱引用会被置为null。要使用弱引用,我们可以将上面的代码改为:

1

2

privateCollection<Observer> observers = Collections.newSetFromMap(

        newWeakHashMap<Observer, Boolean>());

WeakHashMap是一个现成的弱引用Map,Map的键都是弱引用对象。使用WeakHashMap后,被观察者将不会阻止JVM对Observer进行垃圾回收。然而,你必须在代码注释中强调这一点。因为这个特性可能引起一些问题,比如使用者想要注册一个常驻内存的Observer(例如日志库),但他们并没有打算维持一个Observer引用。例如,Android平台上的OnSharedPreferencesChangeListener使用了弱引用,但文档中并没有声明这一特性。这给开发者带来了很多麻烦。

在本文的开头我提到了,现在的很多框架都需要使用者谨慎地管理内存。我想至少有两个例子可以印证这个观点。

Android平台

Android应用程序的核心类采用了基于生命周期的编程模型。这意味着你不能自行创建和管理这些类的实例,这些实例将由Android操作系统在需要的时候替你创建(比如应用程序需要显示某个特定的画面)。同理,Android操作系统将会决定应用何时不再需要某个特定实例(比如用户关闭了应用界面),并通过调用该实例特定的生命周期方法来通知该实例即将被删除。但是,如果你将这个实例的引用泄露到某个全局上下文,Android JVM将不能对这个实例进行回收。这与Android本身的设计理念相违背。由于Android手机通常没有限制应用程序的内存,即使在非常简单的应用中,也会频繁创建和销毁对象,所以在清理引用时必须格外小心。

不幸的是,应用程序核心类引用很容易被泄露到外部。你能看出下面的例子是如何泄露引用的吗?

1

2

3

4

5

6

7

8

9

10

11

12

classExampleActivityextendsActivity {

 

    @Override

    publicvoidonCreate(Bundle bundle) {

        startService(newIntent(this, ExampleService.class).putExtra("mykey",

                newSerializable() {

                    publicString getInfo() {

                        return"myinfo";

                    }

                }));

    }

}

如果你认为是传入Intent构造函数的this指针泄露了当前实例的引用,你就错了。这个Intent对象仅用于启动ExampleService,它会在ExampleService启动之后被销毁。然而,那个实现了Serializable接口的匿名内部类会持有闭包类ExampleActivity的引用。如果ExampleService一直维持着这个匿名类实例引用,那么也会持有这个ExampleActivity实例的引用。

出于这个原因,我建议Android开发者避免使用匿名类。

Web应用框架(特别是Wicket)

Web应用框架通常将半永久性的用户数据存放在Session中。你在Session中写入的任何数据都会在内存中滞留,而且滞留的时间无法确定。如果有一定数量的访问者在你的Session中“乱扔垃圾”,运行Servlet容器的JVM早晚会挂掉。因此,你谨慎管理引用的另一个极端案例就是Wicket框架:Wicket框架会将用户的所有访问序列化成历史版本。这种过分简单的设计意味着,如果某个访问者点击十次欢迎页面,Wicket框架会在硬盘默认路径下序列化十个对象。Wicket页面对象持有的所有对象引用都会和页面对象一起被序列化到硬盘上,所以在管理引用时必须格外小心。

让我们来看一个错误使用Wicket框架的示例:

1

2

3

4

5

6

7

8

classExampleWelcomePageextendsWebPage {

 

    privatefinalList<People> peopleList;

 

    publicExampleWelcomePage (PageParameters pageParameters) {

        peopleList =newService().getWorldPhonebook();

    }

}

用户点击十次欢迎页面,就会在服务器硬盘上存储十份WorldPhoneBook拷贝。因此,在你使用Wicket开发应用时,务必要使用LoadableDetachableModels管理引用。

以上是“Java应用程序中内存泄漏及内存管理的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网行业资讯频道!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java应用程序中内存泄漏及内存管理的示例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java应用程序中内存泄漏及内存管理的示例分析

这篇文章主要介绍Java应用程序中内存泄漏及内存管理的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!btw,一些静态代码扫描工具也能检测出不好的编程习惯带来潜在的内存泄露的风险。Java平台的一个突出的特性是
2023-06-02

JAVA内存泄漏的示例分析

本篇文章给大家分享的是有关JAVA内存泄漏的示例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Java内存泄漏是每个Java程序员都会遇到的问题,程序在本地运行一切正常,可
2023-06-03

JavaScript中内存泄漏的示例分析

这篇文章主要介绍了JavaScript中内存泄漏的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1、识别方法chrome在performance中查看。开启开发工具P
2023-06-15

Java内存泄漏排查的示例分析

这篇文章将为大家详细讲解有关Java内存泄漏排查的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在一个凄凉的午夜午夜刚过,我就被一条来自监控系统的警报吵醒了。Adventory,我们的 PPC (
2023-06-04

Java内存泄漏排查过程的示例分析

这篇文章给大家分享的是有关Java内存泄漏排查过程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。在一个凄凉的午夜午夜刚过,我就被一条来自监控系统的警报吵醒了。Adventory,我们的 PPC (以点击
2023-06-02

C++技术中的内存管理:内存泄漏的典型案例分析

c++++ 中常见的内存泄漏类型包括栈泄漏、堆泄漏和全局泄漏。本文通过一个实战案例分析了堆泄漏。该示例中,一个动态分配的指针在函数返回时丢失了作用域,但分配的内存未释放,导致内存泄漏。可以使用智能指针、手动内存释放或内存检测工具来防止内存泄
C++技术中的内存管理:内存泄漏的典型案例分析
2024-05-08

C++技术中的内存管理:内存泄漏对应用程序性能的影响

c++++ 中的内存管理尤为重要,而内存泄漏会导致严重的性能问题。内存泄漏是指应用程序不再使用分配的内存,导致可用内存减少。这些影响包括速度降低、延迟增加和应用程序崩溃。为了防止内存泄漏,最佳实践包括使用智能指针、使用调试工具和定期释放不再
C++技术中的内存管理:内存泄漏对应用程序性能的影响
2024-05-07

Linux下c++程序内存泄漏检测代码的示例分析

这期内容当中小编将会给大家带来有关如何解决Linux下c++程序内存泄漏检测代码,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Linux下对于程序内存泄漏检测的方法很多,最常用的的莫过于使用valgrin
2023-06-17

java内存管理与内存溢出异常的示例分析

这篇文章主要介绍了java内存管理与内存溢出异常的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。说到内存管理,笔者这里想先比较一下java与C、C++之间的区别:在C
2023-05-31

C++中内存管理的示例分析

这篇文章将为大家详细讲解有关C++中内存管理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。概述内存管理的原理庞大而复杂,然而这些都被操作系统进行了封装,并对外预留了API,这些api被c++调用
2023-06-25

C/C++中指针与内存管理的示例分析

这篇文章主要介绍了C/C++中指针与内存管理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。指针和内存管理始终是C/C++比较容易模糊的知识点,但在C/C++编程中又
2023-06-29

C语言中动态内存管理的示例分析

这篇文章主要介绍了C语言中动态内存管理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。什么是动态内存分配我们都知道在C语言中,定义变量的时候,系统就会为这个变量分配内
2023-06-25

java中JVM运行时内存整理的示例分析

这篇文章给大家分享的是有关java中JVM运行时内存整理的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. 客户端开
2023-06-14

一个分析和解决Java应用程序内存浪费的实战例子,值得收藏!

内存是当今世界上被广泛浪费的硬件资源之一。由于编程效率低下,惊人量的内存浪费被浪费了。这种模式在多个企业应用程序中重复出现。为了证明这种情况,我们进行了一项小型研究。
2023-06-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录