iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >java内存管理关系及内存泄露的原理分析
  • 773
分享到

java内存管理关系及内存泄露的原理分析

2024-04-02 19:04:59 773人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录java内存管理关系及内存泄露原理java对象和内存的关系创建对象null的作用内存泄露检测内存泄露的原理java内存管理关系及内存泄露原理 这可能是最近写的博客中最接近底层的了

java内存管理关系及内存泄露原理

这可能是最近写的博客中最接近底层的了。闲言少叙,进入正题。

java对象和内存的关系

首先,我们要知道下面几条真理(自己总结的)

  • 一个完整的建立对象流程是 1声明对象,2开辟内存空间,3将对象和内存空间建立联系。
  • 一个对象只能对应一个内存空间,一个内存空间可以对应很多对象
  • 回收一个内存空间 。如果,这个内存空间没有任何一个对象和他有联系。就可以被回收,或者好几个对象环形引用,也会被回收
  • 对一个对象进行操作的时候,是先通过 对象 找到 内存空间,然后 对内存空间进行操作(读,写 改 删)

这是本人总结出来的四条经验。

特别重要的是,一定要有这种认知。不管任何语言,最终都是要物理内存上面反映的,对象 和 内存空间 是两个不同的个体。 如果 没有的话,那么你会发现 下面将的都是什么啊!

创建对象


       Stu one; //只声明 one对象 但是没有分配内存空间
        //用new 开辟新的内存空间 oneMemory ,调用构造函数赋值,并将内存空间 oneMemory 与 one对象建立联系。
        one = new Stu("one");
        
        //声明 two对象 并开辟内存 twoMemory 调用构造函数赋值,并将内存空间 twoMemory与 two对象建立联系
        Stu two = new Stu("two");
        
        //声明 three对象, 并找到one 对象联系的内存空间 oneMemory。并将 oneMemory与 three 对象建立联系
        Stu three = one;
        
        //此时 内存空间 oneMemory 与两个对象有联系。一个是 one对象,一个是three对象
        System.out.println("three 和 one 是否相等" + (three == one) + " one的哈希值" + one.hashCode() + " three的哈希值" + three.hashCode());

运行结果

在这里插入图片描述

我们可以发现,three对象 和one对象 指向的是同一个内存空间oneMemory。这个不就是符合上面所说的第二个真理 如果,我们对one对象进行操作,那么产生的影响,也会反映到three对象上。

因为,**他们指向的是同一个内存空间,对one对象操作,就是做内存空间oneMemory进行操作。而three对象指向的也是oneMemory。这个符合上面第四条真理。**例子如下


        System.out.println("three 对象的值" + three.getName() + three.hashCode());
        //修改one的值,第一步 找到one对象联系的内存空间 oneMemory , 将内存空间oneMemory 中的name值改变
        one.setName("change");
        //读取three对象值时候,先找到three对象联系的内存空间oneMemory,读取其中的name值
        System.out.println("three 对象的值" + three.getName() + three.hashCode());

null的作用

长久以来,我只知道,将一个值复制成null,那么他就是空的了。但是 完全不知道,为啥。

还是接着上面的例子,看一段代码;


         //读取three对象值时候,先找到three对象联系的内存空间oneMemory,读取其中的name值
        System.out.println("three 对象的值 before" + three.getName() + three.hashCode());
        
        one = null;
        System.out.println("three 对象的值  after" + three.getName() + three.hashCode());

运行结果

在这里插入图片描述

我们会发现 将one对象赋值为空后,three对象还是和先前一样。以前一直认为null,是将对象和他的内存空间清楚。但现在不是!。代码注释里面写的很清楚了。null 并不是清除内存空间,他只是把对象自己本身和内存空间的联系切断了

内存泄露

如果,你明白了上面。那么内存泄露对你来说也很简单了。

再来学习一个新概念

在这里插入图片描述

上面这么多呢。在本篇文章里面,你只需要记住 被static关键词修饰的变量,类,方法的生命周期是伴随整个程序的。就是程序活多久,他们就活多久

接下来看代码

首先,我们定义一个静态集合 staticList ,他是程序一运行,就会被创建好的。程序结束运行了,它才会被回收。


static List<Stu> staticList = new ArrayList<>();//开辟内存空间 listMemory

       System.out.println("three 对象的值  after" + three.getName() + three.hashCode());
        
        
        staticList.add(three);
        
        
        three = null;
        System.out.println(staticList.get(0).hashCode());

运行结果

在这里插入图片描述

可以看见。在我们将three对象赋值null切断和内存空间 oneMemory的联系后。静态集合staticList对象的部分成员依然和内存空间 oneMemory有联系。根据上面第三条所说,因为内存空间 oneMemory 还是和对象有联系的(staticList)。所以不会回收oneMemory内存空间。又由于staticList是静态的,生命和程序一样长。 那么在整个程序周期里面,oneMemory内存空间 都不会被回收。就造成了内存泄露。

附上完整的代码


package com.zfh.test;
import java.util.ArrayList;
import java.util.List;
public class JavaMain {
    static List<Stu> staticList = new ArrayList<>();//开辟内存空间 listMemory
    public static void main(String[] args) {
        Stu one; //只声明 one对象 但是没有分配内存空间
        //用new 开辟新的内存空间 oneMemory ,调用构造函数赋值,并将内存空间 oneMemory 与 one对象建立联系。
        one = new Stu("one");
        //声明 two对象 并开辟内存 twoMemory 调用构造函数赋值,并将内存空间 twoMemory与 two对象建立联系
        Stu two = new Stu("two");
        //声明 three对象, 并找到one 对象联系的内存空间 oneMemory。并将 oneMemory与 three 对象建立联系
        Stu three = one;
        //此时 内存空间 oneMemory 与两个对象有联系。一个是 one对象,一个是three对象
        System.out.println("three 和 one 是否相等" + (three == one) + " one的哈希值" + one.hashCode() + " three的哈希值" + three.hashCode());
        System.out.println("three 对象的值" + three.getName() + three.hashCode());
        //修改one的值,第一步 找到one对象联系的内存空间 oneMemory , 将内存空间oneMemory 中的name值改变
        one.setName("change");
        //读取three对象值时候,先找到three对象联系的内存空间oneMemory,读取其中的name值
        System.out.println("three 对象的值 before" + three.getName() + three.hashCode());
        
        one = null;
        System.out.println("three 对象的值  after" + three.getName() + three.hashCode());
        
        
        staticList.add(three);
        
        three = null;
        System.out.println(staticList.get(0).hashCode());
    }
}

bean对象 即Stu


package com.zfh.test;
public class Stu {
  
  
    private String name;
    
  
  
    public Stu(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void sout(){
        System.out.println(this.name+this.hashCode());
    }
    public void printer() {
        System.out.println(Stu.class.hashCode());
    }
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("终结了");
    }
}

检测内存泄露的原理

检测内存泄漏的关键是要能截获住对分配内存和释放内存的函数的调用。截获住这两个函数,我们就能跟踪每一块内存的生命周期,比如,每当成功的分配一块内存后,就把它的指针加入一个全局的list中;每当释放一块内存,再把它的指针从list中删除。这样,当程序结束的时候,list中剩余的指针就是指向那些没有被释放的内存。这里只是简单的描述了检测内存泄漏的基本原理,详细的算法可以参见Steve Maguire的<<Writing Solid Code>>。  

如果要检测堆内存的泄漏,那么需要截获住malloc/realloc/free和new/delete就可以了(其实new/delete最终也是用malloc/free的,所以只要截获前面一组即可)。对于其他的泄漏,可以采用类似的方法,截获住相应的分配和释放函数。比如,要检测BSTR的泄漏,就需要截获SysAllocString/SysFreeString;要检测HMENU的泄漏,就需要截获CreateMenu/ DestroyMenu。(有的资源的分配函数有多个,释放函数只有一个,比如,SysAllocStringLen也可以用来分配BSTR,这时就需要截获多个分配函数)。

windows平台下,检测内存泄漏的工具常用的一般有三种,MS C-Runtime Library内建的检测功能;外挂式的检测工具,诸如,Purify,BoundsChecker等;利用Windows NT自带的PerfORMance Monitor。这三种工具各有优缺点,MS C-Runtime Library虽然功能上较之外挂式的工具要弱,但是它是免费的;Performance Monitor虽然无法标示出发生问题的代码,但是它能检测出隐式的内存泄漏的存在,这是其他两类工具无能为力的地方。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: java内存管理关系及内存泄露的原理分析

本文链接: https://www.lsjlt.com/news/137770.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • java内存管理关系及内存泄露的原理分析
    目录java内存管理关系及内存泄露原理java对象和内存的关系创建对象null的作用内存泄露检测内存泄露的原理java内存管理关系及内存泄露原理 这可能是最近写的博客中最接近底层的了...
    99+
    2022-11-12
  • Java内存溢出和内存泄露的示例分析
    这篇文章给大家分享的是有关Java内存溢出和内存泄露的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、为什么要了解内存泄露和内存溢出?内存泄露一般是代码设计存在缺陷导致的,通过了解内存泄露的场景,可以避...
    99+
    2023-05-30
    java
  • Flex内存优化原则和内存泄露的示例分析
    这篇文章将为大家详细讲解有关Flex内存优化原则和内存泄露的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Flex性能优化常用手法众所周知,目前国内的宽带应用并不是像很多发达国家发达,个人应用带宽...
    99+
    2023-06-17
  • Java应用程序中内存泄漏及内存管理的示例分析
    这篇文章主要介绍Java应用程序中内存泄漏及内存管理的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!btw,一些静态代码扫描工具也能检测出不好的编程习惯带来潜在的内存泄露的风险。Java平台的一个突出的特性是...
    99+
    2023-06-02
  • ThreadLocal作用原理与内存泄露示例解析
    目录ThreadLocal作用简单例子局部变量、成员变量 、 ThreadLocal、静态变量共享 or 隔离原理源码分析TheadLocalTheadLocalMapThreadL...
    99+
    2022-11-13
  • C++ 内存管理原理分析
    目录1.C/C++中程序内存分布1.1 内存分布图1.2 小试牛刀2.C语言部分的动态内存管理方式3.C++内存管理方式3.1new/delete操作内置类型3.2 new...
    99+
    2022-11-12
  • Java中内存分配的原理分析
    Java中内存分配的原理分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。深入Java核心Java内存分配原理精讲Java内存分配与管理是Java的核心技术之一,之前我们曾...
    99+
    2023-06-17
  • Java内存泄露的理解与解决是怎样的
    这篇文章给大家介绍Java内存泄露的理解与解决是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java内存管理机制在C++ 语言中,如果需要动态分配一块内存,程序员需要负责这块内存的整个生命周期。从申请分配、到使...
    99+
    2023-06-17
  • java内存管理与内存溢出异常的示例分析
    这篇文章主要介绍了java内存管理与内存溢出异常的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。说到内存管理,笔者这里想先比较一下java与C、C++之间的区别:在C...
    99+
    2023-05-31
    java
  • Java内存泄露监控工具以及JVM监控工具的实例分析
    Java内存泄露监控工具以及JVM监控工具的实例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。jstack -- 如果java程序崩溃生成core文件,jstack工具...
    99+
    2023-06-17
  • 分析Netty直接内存原理及应用
    目录一、通常的内存模型概述二、Java中的直接内存原理三、Netty中使用直接内存四、总结一、通常的内存模型概述 一般地,系统为了保证系统本身的安全性和健壮性,会将内存从逻辑上隔离成...
    99+
    2022-11-12
  • 分析JS中的内存管理
    这篇文章主要讲解了“分析JS中的内存管理”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“分析JS中的内存管理”吧!前言像C语言这样的底层语言一般都有底层的内存...
    99+
    2022-10-19
  • Linux内存管理之内存回收的示例分析
    这篇文章主要介绍了Linux内存管理之内存回收的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1.1 内存回收的目标不是所有的物理内存都可以参与回收的,比如要是把内核...
    99+
    2023-06-16
  • MySQL内存管理,内存分配器和操作系统的示例分析
    这篇文章主要介绍MySQL内存管理,内存分配器和操作系统的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!当用户使用任何软件(包括MySQL)碰到内存问题时,我们第一反应就是内...
    99+
    2022-10-18
  • 分析Java内存管理与垃圾回收
    这篇文章主要介绍“分析Java内存管理与垃圾回收”,在日常操作中,相信很多人在分析Java内存管理与垃圾回收问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”分析Java内存管理...
    99+
    2022-10-19
  • Python的内存管理举例分析
    这篇文章主要介绍“Python的内存管理举例分析”,在日常操作中,相信很多人在Python的内存管理举例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python的内存管理举例分析”的疑惑有所帮助!接下来...
    99+
    2023-06-17
  • Python中的内存管理的原理和机制是什么,如何避免内存泄漏?
    Python中的内存管理的原理和机制是什么,如何避免内存泄漏?Python作为一门高级语言,通过自动内存管理提供了方便的编程环境。Python的内存管理主要依靠垃圾回收机制来实现,通过引用计数和循环垃圾回收来管理和释放内存。在Python中...
    99+
    2023-10-22
    内存管理:内存管理 原理:原理 内存泄漏:内存泄漏
  • C/C++内存管理的示例分析
    这篇文章主要介绍了C/C++内存管理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。C/C++赋予程序员管理内存的自由,是C/C++语言特色,虽然这引入了复杂度和危险...
    99+
    2023-06-15
  • C++中内存管理的示例分析
    这篇文章将为大家详细讲解有关C++中内存管理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。概述内存管理的原理庞大而复杂,然而这些都被操作系统进行了封装,并对外预留了API,这些api被c++调用...
    99+
    2023-06-25
  • JS中内存管理的示例分析
    这篇文章将为大家详细讲解有关JS中内存管理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言像C语言这样的底层语言一般都有底层的内存管理接口,比如 malloc...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作