精华内容
下载资源
问答
  • 闭包会导致内存泄漏
    2021-09-25 17:38:13

    刷面经的时候学到的是闭包内引用的变量不会被回收,会导致内存泄漏。看了红宝书(js高级程序设计)的原话是:

    由于IE在IE9之前对jScript对象和COM对象使用了不同的垃圾回收机制,所以闭包在这些旧版本IE中可能会导致问题。在这些版本的IE中,把HTML元素保存在某个闭包的作用域,就相当于宣布该元素不能被销毁。

    function assignHandler(){
    	let element = document.getElementById('someElement')'
    	element.onclick = () => console.log(element.id)
    }
    

    上面这段代码的elemen.id,就是闭包对另一个函数作用域的变量的引用,阻止了对element的引用计数归零,则这个变量不会被内存回收。

    将代码更改为

    function assignHandler(){
    	let element = document.getElementId('someElement')
    	let id = element.id //消除引用循环
    	element.onclick = () => console.log(id)
    	element = null //解除对这个对象的引用
    }
    

    element的引用计数归零,内存就可以回收了。

    所以闭包不会导致内存泄漏,而是旧版本的浏览器的垃圾回收机制存在问题,通过一些处理就可以避免内存无法回收的问题。

    有错误烦请指正。

    更多相关内容
  • 详细可参考博文:原创 android内存泄露:3、Handler的错误使用导致内存泄露 ,这篇文章我们将介绍:Toast的错误使用导致内存泄露 二、Toast的错误使用导致内存泄露 我们通常,连续点击按钮多次提示的 Toast,它...
  • 内存泄露的危害就是会使虚拟机占用内存过高,导致OOM(内存溢出),程序出错。接下来通过本文给大家分享Android使用Handler造成内存泄露问题及解决方法,一起看看吧
  • Vue单页面应用中:Web App 与 传统Web的区别,因为Web App是单页面应用页面通过路由跳转不会刷新页面,导致内存泄漏不断堆积,导致页面卡顿。 泄漏点: 1.DOM/BOM 对象泄漏 2.script 中存在对DOM/BOM 对象的引用导致...
  • 所以只要线程存活,GC就不可能把Entry回收,造成内存泄露。 如何避免内存泄露 由图中的引用链可知,只要线程还存活,就一定会有内存泄露的问题。因此避免泄露的方法一: 使用完ThreadLocal,当前Thread也随之运行...

    ThreadLocal的引用在jvm中如下图:
    在这里插入图片描述
    因为CurrentThreadRef -> CurrentThread -> Map -> Entry该引用链是强引用,所以Entry的生命周期与线程一致。所以只要线程存活,GC就不可能把Entry回收,造成内存泄露。

    如何避免内存泄露

    由图中的引用链可知,只要线程还存活,就一定会有内存泄露的问题。因此避免泄露的方法一:
    使用完ThreadLocal,当前Thread也随之运行结束。
    还有一种更直接的方法二:
    使用完ThreadLocal,调用其remove方法删除对应的Entry

    为什么使用弱引用

    首先,java的弱引用(WeakReference),在发生GC时,无论内存是否足够,都会进行垃圾回收。
    ThreadLocal使用完毕之后,EntryKey便被回收变为null。在ThreadLocalMap中的set/getEntry方法中,会对keynull(也即是ThreadLocalnull)进行判断,如果为null的话,那么是会对value置为null的。
    这就意味着使用完ThreadLocalCurrentThread依然运行的前提下,就算忘记调用remove方法,弱引用比强引用可以多一层保障:弱引用的ThreadLocal会被回收,对应的value在下一次ThreadLocalMap调用set,get,remove中的任一方法的时候会被清除,从而避免内存泄漏。

    展开全文
  • 之前一直盲目的认为 Python 不会存在内存泄露, 但是眼看着上线的项目随着运行时间的增长 而越来越大的内存占用, 我意识到我写的程序在发生内存泄露, 之前 debug 过 logging 模块导致内存泄露. 目前看来, 还有别的...
  • vue的自定义指令是一个比较容易引起内存泄漏的地方,原因就在于指令通常给元素绑定了事件,但是如果忘记了解绑,就会产生内存泄漏的问题。 看下面代码: directives: { scroll: { inserted (el, cb) { // 不是...
  • Android 内存溢出和内存泄漏的问题 在面试中,经常有面试官会问“你知道什么是内存溢出?什么是内存泄漏?...内存泄漏最终会导致内存溢出。 如何避免内存溢出? 强引用:强引用是使用最普遍的引用。如果一个
  • 主要介绍了浅谈js 闭包引起的内存泄露问题的相关资料,需要的朋友可以参考下
  • 在这个相关的技巧中,我将带您了解嵌套类的陷阱之一,这是内部类在JVM中导致内存泄漏和内存不足错误的潜力。 之所以会发生这种类型的内存泄漏,是因为内部类必须始终能够访问其外部类-并非总是与JVM的计划一起使用。...
  • 主要介绍了IOS 常见内存泄漏以及解决方案的相关资料,需要的朋友可以参考下
  • 但如果不重启tomcat而对web应用进行重加载则可能会导致内存泄漏,因为重加载后有可能会导致原来的某些内存无法让GC回收,例如web应用使用了JDBC,驱动会进行注册,当web应用停止时没有反注册就会导致内存泄漏。...
  • 无穷大导致内存泄漏 如果把内存泄漏定义成只申请不释放,那么借着 Python 中整数可以无穷大的这个特点,我们一行代码就可以完成内存泄漏了。 i = 1024 ** 1024 ** 1024 循环引用导致内存泄漏 引用记数器 是 Python ...
  • 概念内存泄露:指程序中动态分配内存给一些临时对象,但对象不会被GC回收,它始终占用内存,被分配的对象可达但已无用。即无用对象持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间浪费。可达性分析...

    概念

    内存泄露:指程序中动态分配内存给一些临时对象,但对象不会被GC回收,它始终占用内存,被分配的对象可达但已无用。即无用对象持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间浪费。

    可达性分析算法

    JVM使用可达性分析算法判断对象是否存活。

    GC Root

    通过一系列名为“GC Roots”的对象作为起点,从这些结点开始向下搜索,搜索所走过的路径称为“引用链(Reference Chain)”,当一个对象到GC Roots没有任何饮用链相连时,则证明此对象是不可用的。

    21e992069c3b54ecb576b5f9045cc44f.png

    object4、object5、object6虽然有互相判断,但是它们到GC Rootd是不可达的,所以它们将会判定为是可回收对象。

    可以作为GC Roots的对象有:虚拟机栈(栈帧中的本地变量表)中的引用的对象;

    方法区中的类静态属性引用的对象;

    方法区中的常量引用的对象;

    本地方法栈中JNI的引用的对象

    虽然Java有垃圾收集器帮组实现内存自动管理,虽然GC有效的处理了大部分内存,但是并不能完全保证内存的不泄漏。

    内存泄漏

    内存泄漏就是堆内存中不再使用的对象无法被垃圾收集器清除掉,因此它们会不必要地存在。这样就导致了内存消耗,降低了系统的性能,最终导致OOM使得进程终止。

    内存泄漏的表现:应用程序长时间连续运行时性能严重下降;

    应用程序中的OutOfMemoryError堆错误;

    自发且奇怪的应用程序崩溃;

    应用程序偶尔会耗尽连接对象;

    可能导致内存泄漏的原因:

    1. static字段引起的内存泄漏

    大量使用static字段会潜在的导致内存泄漏,在Java中,静态字段通常拥有与整个应用程序相匹配的生命周期。

    解决办法:最大限度的减少静态变量的使用;单例模式时,依赖于延迟加载对象而不是立即加载的方式(即采用懒汉模式,而不是饿汉模式)

    2. 未关闭的资源导致内存泄漏

    每当创建连接或者打开流时,JVM都会为这些资源分配内存。如果没有关闭连接,会导致持续占有内存。在任意情况下,资源留下的开放连接都会消耗内存,如果不处理,就会降低性能,甚至OOM。

    解决办法:使用finally块关闭资源;关闭资源的代码,不应该有异常;JDK1.7之后,可以使用太try-with-resource块。

    3. 不正确的equals()和hashCode()

    在HashMap和HashSet这种集合中,常常用到equal()和hashCode()来比较对象,如果重写不合理,将会成为潜在的内存泄漏问题。

    解决办法:用最佳的方式重写equals()和hashCode().

    4. 引用了外部类的内部类

    非静态内部类的初始化,总是需要外部类的实例;默认情况下,每个非静态内部类都包含对其外部类的隐式引用,如果我们在应用程序中使用这个内部类对象,那么即使在我们的外部类对象超出范围后,它也不会被垃圾收集器清除掉。

    解决办法:如果内部类不需要访问外部类包含的类成员,可以转换为静态类。

    5. finalize方法导致的内存泄漏

    重写finalize()方法时,该类的对象不会立即被垃圾收集器收集,如果finalize()方法的代码有问题,那么会潜在的印发OOM;

    解决办法:避免重写finalize()方法。

    6. 常量字符串造成的内存泄漏

    如果我们读取一个很大的String对象,并调用了intern(),那么它将放到字符串池中,位于PermGen中,只要应用程序运行,该字符串就会保留,这就会占用内存,可能造成OOM。(针对JDK1.6及以前,常量池在PermGen永久代中)

    解决办法:增加PermGen的大小,-XX:MaxPermSize=512M;JDK1.7以后字符串池转移到了堆中。

    intern()方法详解:String str1 = "abc";

    String str2 = "abc";

    String str3 = new String("abc");

    String str4 = str3.intern();

    System.out.println(str1 == str2);

    System.out.println(str2 == str3);

    System.out.println(str1 == str4);

    System.out.println(str3 == str4);

    true, false, true, false

    intern()方法搜索字符串常量池,如果存在指定的字符串,就返回之;

    否则,就将该字符串放入常量池并返回之。

    换言之,intern()方法保证每次返回的都是 同一个字符串对象String str1 = "abc";

    String str2 = "abc";

    String str3 = new String("abcd");

    String str4 = str3.intern();

    String str5 = "abcd";

    System.out.println(str1 == str2);

    System.out.println(str2 == str3);

    System.out.println(str1 == str4);

    System.out.println(str3 == str4);

    System.out.println(str4 == str5);

    true

    false

    false

    false

    true

    为何要使用intern()方法?看看equals方法的源码:public boolean equals(Object anObject) {

    if (this == anObject) {

    return true;

    }

    if (anObject instanceof String) {

    String anotherString = (String)anObject;

    int n = value.length;

    if (n == anotherString.value.length) {

    char v1[] = value;

    char v2[] = anotherString.value;

    int i = 0;

    while (n-- != 0) {

    if (v1[i] != v2[i])

    return false;

    i++;

    }

    return true;

    }

    }

    return false;

    }

    可以看到,比较两个字符串的时候,首先比较两个字符串对象是否地址相同,不同再挨个比较字符。这样就大大加快了比较的速度。否则若每次都挨个比较将是非常耗时的。

    7. 使用ThreadLocal造成内存泄漏

    使用ThreadLocal时,每个线程只要处于存活状态就可保留对其ThreadLocal变量副本的隐式调用,且将保留其自己的副本。使用不当,就会引起内存泄漏。

    一旦线程不再存在,该线程的threadLocal对象就应该被垃圾收集,而现在线程的创建都是使用线程池,线程池有线程重用的功能,因此线程就不会被垃圾回收器回收。所以使用到ThreadLocal来保留线程池中的线程的变量副本时,ThreadLocal没有显式地删除时,就会一直保留在内存中,不会被垃圾回收。

    解决办法:不再使用ThreadLocal时,调用remove()方法,该方法删除了此变量的当前线程值。不要使用ThreadLocal.set(null),它只是查找与当前线程关联的Map并将键值中这个threadLocal对象所对应的值为null,并没有清除这个键值对。

    最后

    感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

    展开全文
  • 今天小编就为大家分享一篇解决Tensorflow 内存泄露问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 今天介绍一个String使用不当可能导致内存泄露的问题,主要围绕其subString方法。围绕String和subString也有很多面试题,是比较重要的知识点。 substring(int beginIndex, int endIndex)方法在不同版本的JDK中的实现...

    String是Java中一个比较基础的类,每一个开发人员都会经常接触到。而且,String也是面试中经常会考的知识点。String有很多方法,有些方法比较常用,有些方法不太常用。

    今天介绍一个String使用不当可能导致内存泄露的问题,主要围绕其subString方法。围绕String和subString也有很多面试题,是比较重要的知识点。

    substring(int beginIndex, int endIndex)方法在不同版本的JDK中的实现是不同的。了解他们的区别可以帮助你更好的使用他。为简单起见,后文中用substring()代表substring(int beginIndex, int endIndex)方法。

    图片

    substring() 的作用

    图片

    substring(int beginIndex, int endIndex)方法截取字符串并返回其[beginIndex,endIndex-1]范围内的内容。

    String x = "abcdef";
    x = x.substring(1,3);
    System.out.println(x);
    

    输出内容:

    bc
    

    图片

    调用substring()时发生了什么?

    图片

    你可能知道,因为x是不可变的,当使用x.substring(1,3)对x赋值的时候,它会指向一个全新的字符串:

    图片

    然而,这个图不是完全正确的表示堆中发生的事情。因为在jdk6 和 jdk7中调用substring时发生的事情并不一样。

    图片

    JDK 6中的substring

    图片

    String是通过字符数组实现的。在jdk 6 中,String类包含三个成员变量:char value[], int offsetint count。他们分别用来存储真正的字符数组,数组的第一个位置索引以及字符串中包含的字符个数。

    当调用substring方法的时候,会创建一个新的string对象,但是这个string的值仍然指向堆中的同一个字符数组。这两个对象中只有count和offset 的值是不同的。

    图片

    下面是证明上说观点的Java源码中的关键代码:

    //JDK 6
    String(int offset, int count, char value[]) {
        this.value = value;
        this.offset = offset;
        this.count = count;
    }
    
    public String substring(int beginIndex, int endIndex) {
        //check boundary
        return  new String(offset + beginIndex, endIndex - beginIndex, value);
    }
    

    图片

    substring与内存泄露

    图片

    如果你有一个很长很长的字符串,但是当你使用substring进行切割的时候你只需要很短的一段。

    这可能导致性能问题,因为你需要的只是一小段字符序列,但是你却引用了整个字符串(因为这个非常长的字符数组一直在被引用,所以无法被回收,就可能导致内存泄露)。

    在JDK 6中,一般用以下方式来解决该问题,原理其实就是生成一个新的字符串并引用他。

    x = x.substring(x, y) + ""
    

    关于JDK 6中subString的使用不当会导致内存系列已经被官方记录在Java Bug Database中:

    图片

     

    内存泄露:在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。 内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。

    图片

    JDK 7 中的substring

    图片

    上面提到的问题,在jdk 7中得到解决。在jdk 7 中,substring方法会在堆内存中创建一个新的数组。

    图片

    Java源码中关于这部分的主要代码如下:

    //JDK 7
    public String(char value[], int offset, int count) {
        //check boundary
        this.value = Arrays.copyOfRange(value, offset, offset + count);
    }
    
    public String substring(int beginIndex, int endIndex) {
        //check boundary
        int subLen = endIndex - beginIndex;
        return new String(value, beginIndex, subLen);
    }
    

    以上是JDK 7中的subString方法,其使用new String创建了一个新字符串,避免对老字符串的引用。从而解决了内存泄露问题。

    所以,如果你的生产环境中使用的JDK版本小于1.7,当你使用String的subString方法时一定要注意,避免内存泄露。

    图片

    福利时间

    图片

    8月第2次送书活动,上一次活动地址:Hollis公众号8月送书活动~,中奖的10位朋友的书籍已经安排寄出。

    本次送出技术书籍 4 本。感谢关注Hollis,除了大量原创技术文章推送外,每月还会开展多次送书活动。如果你觉得Hollis对你有帮助,欢迎推荐给你身边的朋友。

    在介绍书籍之前,请允许我简单宣传一下我的知识星球,不感兴趣的可以跳过本段直接到文末查看活动介绍。

    我的知识星球<Hollis和他的朋友们>建立大概有四个月了,目前有球友600+,是一个付费的知识学习圈子,里面有很好的学习氛围。

    前面这个关于String的问题,也是由目前星球中开展的成神之路第010期引出的。

    目前主要有三个重要的板块。直面Java、成神之路、错题集。

    直面Java:每天给出一道面试题,球友讨论。第二天给出答案。目前已经进行了100+期。

    成神之路:每1-2周,抛出一个知识点,球友自主学习及相互讨论,通过交作业形式写出个人总结。点赞排名第一的我送技术书籍一本。

    错题集:球友们会把日常工作中遇到问题及解决防方案记录到这里面。

    感兴趣的朋友可以扫描下方二维码加入。

    展开全文
  • 但是如果有一系列对象对这个对象的引用,那么在我们期望这个对象生命周期结束的时候被GC回收的时候,它是不会被回收的,它还会占用内存,导致堆内存直升不降,这就造成了内存泄露内存泄漏: 指对象不再使用,...
  • 2、setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏 3、闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环) Js内存泄露解决方法 1.global variables:对未声明的变量的...
  • 如果线程是永久运行的,那么将永远无法释放,因为在Java中线程是垃圾回收机制的根源,在运行系统中DVM虚拟机总会硬件持有所有运行状态的进程的引用,结果导致处于运行状态的线程将永远不会被回收,导致内存泄漏。...
  • 主要介绍了PHP CURL 内存泄露问题解决方法,CRUL长时间访问HTTPS网站时有内存泄露问题,本文经过反复调试找到了解决方法,需要的朋友可以参考下
  • `JavaScript`中的内存管理标记清除算法步骤闭包造成内存泄漏的情况最后是其他情况的内存泄漏1. 意外的全局变量2. 被遗忘的计时器或回调3. 超出`DOM`引用 从变量开始 1. 变量分类 基本数据类型 指简单的数据段 存储...
  • 主要介绍了详解Android使用Handler造成内存泄露的分析及解决方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 主要介绍了一个Vue页面的内存泄露分析详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 而现在流行的C#和Java等语言采用了自动垃圾回收方法管理内存,正常使用的情况下几乎不会发生内存泄露。浏览器中也是采用自动垃圾回收方法管理内存,但由于浏览器垃圾回收方法有bug,会产生内存泄露。1、当页面中元素...
  • 通过一个Demo来简要介绍下ThreadLocal和ClassLoader导致内存泄露最终OutOfMemory的场景。下面通过示例代码给大家分享Java内存泄露的相关知识,感兴趣的朋友一起看看吧
  • 如何解决Python2的内存泄漏问题python本身不会造成内存泄露,如果用的C/C++写的模块(包),如果处理不好,可能会造成内存泄露,但是也是C/C++的模块造成的欢迎来到四十五资源网,python本身不会造成内存泄露,如果用的C/...
  • 今天看到一篇关于js使用中内存泄露的文章,以及chrom浏览器查看内存泄漏的方法,决定留着。本文只截取了我认为比较重要的部分,喜欢原文的小伙伴,请点击文章下方的原文链接。 什么是内存泄露?内存泄露是指new了一...
  • 内存泄漏原因: 对接的webservice接口,使用了XStream,并且在遍历每条数据的时候都new了一个XStream。 XStream官方有一段话:The XStream instance is thread-safe. That is, once the XStream instance has been ...
  • Map 导致内存泄露

    2021-05-19 16:43:07
    Map导致内存泄露1.关于这个内存泄露场景,有诸多不解,特此记录1.1.测试内存泄露操作,及解决办法1.2.为了找到泄露的原因,途中发现一个不解之处,推测2.Map内存泄露原因包含2.1.Map是长生命周期,value含有短生命...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 263,267
精华内容 105,306
关键字:

不会造成内存泄漏的使用方式