精华内容
参与话题
问答
  • 内存泄露

    2019-11-01 22:57:28
    什么是内存泄露: 内存泄漏就是申请了空间却没有成功释放,或者是申请了空间,却丢失了指向该空间的指针,造成内存无法操控, 危害: 内存泄漏会导致系统变慢,卡顿,甚至卡死。 长期运行的程序出现内存泄漏,影响,...

    什么是内存泄露:

    内存泄漏就是申请了空间却没有成功释放或者是申请了空间,却丢失了指向该空间的指针,造成内存无法操控,

    危害:

    内存泄漏会导致系统变慢,卡顿,甚至卡死。
    长期运行的程序出现内存泄漏,影响,如操作系统,后台服务等,影响很大。

    内尺寸泄露的分类:(了解)
    C/C++ :
    程序中一般我们古纳辛两方面:
    1 堆内存泄漏
    malloc calloc relloc new 等创建出来的空间没有及时调用相应的delete释放掉,
    切记: 申请空间和释放空间操作符一定要匹配使用,不匹配可能出错;

    2 系统资源泄露 :
    比方套接字 ,文件描述符。管道等对应的函数没有释放掉。

    如何检测内存泄漏
    1 Linux下检测:有相应几款工具
    2 windows 下 第三方工具 VLD

    3 其他工具

    内存泄露的解决方案:
    1 智能指针——————事前预防
    2 检测工具——————事后查错

    如何避免:
    1 申请记得释放(不一定有效(异常安全导致走不到释放的指令),所以还得智能指针管理),
    2 采用 RALL思想或智能指针来管理资源;
    3:有些公司有检漏工具
    4 出错再捡漏(工具靠谱性低,代价高)

    展开全文
  • if (!(Test-Path -Path $PROFILE)) { New-Item -ItemType File -Path $PROFILE -Force }

    1. 先说问题背景:生产环境IIS站点,运行一段时间后,w3wp进程内存会涨到2G,同时内存不释放。

    在这里插入图片描述

    2. 问题确认

    打开性能计数器,我们重点看一段时间内,IIS站点w3wp进程相关的性能计数器的变化:
    在这里插入图片描述
    性能计数器中:有三个非常重要:

    .NET CLR Memory/Gen 2 heap size
    .NET CLR Memory/Gen 1 heap size
    .NET CLR Memory/Gen 0 heap size
    托管堆上的对象有三代:
    第 0 代: 这是最年轻的代,其中包含短生存期对象。 短生存期对象的一个示例是临时变量。 垃圾回收最常发生在此代中。新分配的对象构成新一代的对象并且为隐式的第 0 代回收,除非它们是大对象,在这种情况下,它们将进入第 2 代回收中的大对象堆。大多数对象通过第 0 代中的垃圾回收进行回收,不会保留到下一代。
    第 1 代: 这一代包含短生存期对象并用作短生存期对象和长生存期对象之间的缓冲区。
    第 2 代: 这一代包含长生存期对象。 长生存期对象的一个示例是服务器应用程序中的一个包含在进程期间处于活动状态的静态数据的对象。 当条件得到满足时,垃圾回收将在特定代上发生。 回收某个代意味着回收此代中的对象及其所有更年轻的代。 第 2 代垃圾回收也称为完整垃圾回收FullGC,因为它回收所有代上的所有对象(即,托管堆中的所有对象)。
    幸存和提升:垃圾回收中未回收的对象也称为幸存者,并会被提升到下一代。 在第 0 代垃圾回收中幸存的对象将被提升到第 1 代;在第 1 代垃圾回收中幸存的对象将被提升到第 2 代;而在第 2 代垃圾回收中幸存的对象将仍为第 2 代。
    通过代提升,看对象的存活时间!

    Process/Private Bytes
    Process/Virtual Bytes
    .NET CLR Memory/# Bytes in all Heaps : CLR内存托管堆的大小
    .NET CLR Memory/Large Object Heap Size: 大对象堆包含其大小为 85,000 个字节和更多字节的对象。
    在这里插入图片描述
    托管堆的内存大小增加的趋势和大对象堆增加的趋势重叠,可以初步推断,内存的增加和大对象有关系!

    3. 梳理问题分析思路

    连续、间隔抓两个或者三个Dump,每次抓Dump间隔半个小时,或者一个小时,主要看内存的增量。
    在这里插入图片描述
    对比的看每个Dump中:

    • 多核CPU情况下,分析每个GC托管堆的大小 !eeheap –gc
    • 查询内存中各类对象的总个数和总内存占用 !dumpheap –stat
    • 查询内存中大对象的个数和对象大小 !dumpheap –stat -mt -min 5000 -max 100000
    • 如果某一类或者几类对象的内存总占用很多,分析此类对象 !dumpheap –mt ***
    • 多次采样查看步骤4中对象的gcroot !gcroot addr
    • 打断gcroot中任何一个链条,释放对象引用
    • 动手分析
    • 多核CPU情况下,分析每个GC托管堆的大小 !eeheap –gc
      在这里插入图片描述
    • 查询内存中各类对象的总个数和总内存占用 !dumpheap –stat
      在这里插入图片描述
    • 查询内存中大对象的个数和对象大小 !dumpheap –stat -mt -min 5000 -max 100000
      在这里插入图片描述
    • 如果某一类或者几类对象的内存总占用很多,分析此类对象 !dumpheap –mt *** -stat
      在这里插入图片描述
      大对象字符串分析,Session会话数据!同时Session会话中包含了权限数据!
    • 多次采样查看步骤4中对象的gcroot !gcroot addr
      在这里插入图片描述
    • 打断gcroot中任何一个链条,释放对象引用

    4. 总结

    总结一下,内存泄露问题分析,有固定的方法和指令,过程需要大家深入理解,同时熟悉代码非常重要,因为需要找出gcroot,分析出内存泄露的原因,再进行修改解决。

    大的套路:

    • 描述问题背景和现象
    • 确定问题是否是内存泄露
    • 梳理问题分析思路
    • 动手分析解决
    • 总结

    详细的分析步骤:

    • 多核CPU情况下,分析每个GC托管堆的大小 !eeheap –gc
    • 查询内存中各类对象的总个数和总内存占用 !dumpheap –stat
    • 查询内存中大对象的个数和对象大小 !dumpheap –stat -mt -min 5000 -max 100000
    • 如果某一类或者几类对象的内存总占用很多,分析此类对象 !dumpheap –mt ***
    • 多次采样查看步骤4中对象的gcroot !gcroot addr
    • 打断gcroot中任何一个链条,释放对象引用
    展开全文
  • 内存泄露

    2009-10-27 18:26:00
    内存泄露是指程序中间动态分配了内存,但是在程序结束时没有释放这部分内存,从而造成那一部分内存不可用的情况,重起计算机可以解决,但是也有可能再次发生内存泄露内存泄露和硬件没有关系,它是由软件设计缺陷...

      内存泄露是指程序中间动态分配了内存,但是在程序结束时没有释放这部分内存,从而造成那一部分内存不可用的情况,重起计算机可以解决,但是也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起的。

    应用程序一般使用malloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存

    块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。所以malloc后一定要free,new了之后一定要delete,creatDC之后一定要deleteDC的。

     

    内存泄漏可以分为4类:1. 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。

      2. 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
     
      3. 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
     
      4. 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

    例子:

    void   f1(void)   

      {   
            int   *   p;     
            p   =   new   int;   
      }   
        
      执行了F1函数后,p所分配到的内存地址就丢了。找不回那个int内存了,所以这里的内存泄露了!一般多是指内存分配未回收。

    .用   malloc   分配了,但没有用   free   释放。   

      2.用   new   分配了,但没有用   delete   删除。   
      3.用   GlobalAlloc   分配,但没有用   GlobalFree   释放。   
      4.用   new   []   分配的数组,没有用   delete[]   删除,而是用   delete   删除。   
      如:   
          struct   A   {   
                int   num;   
          }   
        
          struct   A*   pa;   
          pa   =   new   A[10];   
          delete   pa;   //应该用delete[]   pa;

    展开全文
  • ThreadLocal原理及内存泄露预防

    万次阅读 多人点赞 2018-05-24 13:38:21
    内存泄露 线程池 参阅:http://www.importnew.com/22039.html 前言 ThreadLocal提供了线程独有的局部变量,可以在整个线程存活的过程中随时取用,极大地方便了一些逻辑的实现。常见的ThreadLocal用法有: ...


    参阅:http://www.importnew.com/22039.html

    前言

    ThreadLocal提供了线程独有的局部变量,可以在整个线程存活的过程中随时取用,极大地方便了一些逻辑的实现。常见的ThreadLocal用法有:

    • 存储单个线程上下文信息。比如存储id等;
    • 使变量线程安全。变量既然成为了每个线程内部的局部变量,自然就不会存在并发问题了;
    • 减少参数传递。比如做一个trace工具,能够输出工程从开始到结束的整个一次处理过程中所有的信息,从而方便debug。由于需要在工程各处随时取用,可放入ThreadLocal。

    原理

    每个Thread内部都有一个Map,我们每当定义一个ThreadLocal变量,就相当于往这个Map里放了一个key,并定义一个对应的value。每当使用ThreadLocal,就相当于get(key),寻找其对应的value。

    每个Thread都有一个{@link Thread#threadLocals}变量,它就是放k-v的map,类型为{@link java.lang.ThreadLocal.ThreadLocalMap}。这个map的entry是{@link java.lang.ThreadLocal.ThreadLocalMap.Entry},具体的key和value类型分别是{@link ThreadLocal}(我们定义ThreadLocal变量就是在定义这个key)和 {@link Object}(我们定义ThreadLocal变量的值就是在定义这个value)。

    (注:实际上key是指向ThreadLocal类型变量的弱引用WeakReference<ThreadLocal<?>>,但可以先简单理解为ThreadLocal。)

    当设置一个ThreadLocal变量时,这个map里就多了一对ThreadLocal -> Object的映射。

    ThreadLocal示意图

    通过一个简单程序来说明上图:

    package example.concurrency.tl;
    
    /**
     * @author liuhaibo on 2018/05/23
     */
    public class ThreadLocalDemo {
    
        private static final ThreadLocal<Integer> TL_INT = ThreadLocal.withInitial(() -> 6);
        private static final ThreadLocal<String> TL_STRING = ThreadLocal.withInitial(() -> "Hello, world");
    
        public static void main(String... args) {
    	    // 6
            System.out.println(TL_INT.get());
            TL_INT.set(TL_INT.get() + 1);
            // 7
            System.out.println(TL_INT.get());
            TL_INT.remove();
            // 会重新初始化该value,6
            System.out.println(TL_INT.get());
        }
    }
    

    分析一下其中一个ThreadLocal变量TL_INTJVM运行时数据区的位置:

    • Stack-ThreadLocalRef:TL_INT,变量的引用,在栈上;
    • Stack-CurrentThreadRef: 当前线程的线程栈,线程私有变量的引用都在线程栈上;
    • Heap-ThreadLocal:TL_INT引用所对应的ThreadLocal实例对象;
    • Heap-Map:当前线程内部的threadLocals变量所对应的map实例;
    • Heap-Entry:上述map的entry;
    • Heap-Entry-Key:上述entry的键的弱引用
    • Heap-Entry-Value:上述entry的值的强引用

    对于上述程序,实际上我们在当前线程的threadlocals这个map里放了如下内容:

     | TL_INT    -> 6 |
     | TL_STRING -> "Hello, world"|
    

    对于一个普通的map,取其中某个key对应的值分两步:

    1. 找到这个map;
    2. 在map中,给出key,得到value。

    想取出我们存放在当前线程里的map里的值同样需要这两步。但是,我们不需要告诉jvm map在哪儿,因为jvm知道当前线程,也知道其局部变量map。所以最终的get操作只需要知道key就行了:int localInt = TL_INT.get();
    看起来有些奇怪,不同于常规的map的get操作的接口的样子。

    为什么key使用弱引用

    不妨反过来想想,如果使用强引用,当ThreadLocal对象(假设为ThreadLocal@123456)的引用(即:TL_INT,是一个强引用,指向ThreadLocal@123456)被回收了,ThreadLocalMap本身依然还持有ThreadLocal@123456的强引用,如果没有手动删除这个key,则ThreadLocal@123456不会被回收,所以只要当前线程不消亡,ThreadLocalMap引用的那些对象就不会被回收,可以认为这导致Entry内存泄漏。

    那使用弱引用的好处呢?

    如果使用弱引用,那指向ThreadLocal@123456对象的引用就两个:TL_INT强引用,和ThreadLocalMap中Entry的弱引用。一旦TL_INT被回收,则指向ThreadLocal@123456的就只有弱引用了,在下次gc的时候,这个ThreadLocal@123456就会被回收。

    那么问题来了,ThreadLocal@123456对象只是作为ThreadLocalMap的一个key而存在的,现在它被回收了,但是它对应的value并没有被回收,内存泄露依然存在!而且key被删了之后,变成了null,value更是无法被访问到了!针对这一问题,ThreadLocalMap类的设计本身已经有了这一问题的解决方案,那就是在每次get()/set()/remove()ThreadLocalMap中的值的时候,会自动清理key为null的value。如此一来,value也能被回收了。

    既然对key使用弱引用,能使key自动回收,那为什么不对value使用弱引用?答案显而易见,假设往ThreadLocalMap里存了一个value,gc过后value便消失了,那就无法使用ThreadLocalMap来达到存储全线程变量的效果了。(但是再次访问该key的时候,依然能取到value,此时取得的value是该value的初始值。即在删除之后,如果再次访问,取到null,会重新调用初始化方法。)

    内存泄露

    总结一下内存泄露(本该回收的无用对象没有得到回收)的原因:

    • 弱引用一定程度上回收了无用对象,但前提是开发者手动清理掉ThreadLocal对象的强引用(如TL_INT)。只要线程一直不死,ThreadLocalMap的key-value一直在涨。

    解决方法:当某个ThreadLocal变量(比如:TL_INT)不再使用时,记得TL_INT.remove(),删除该key。

    比如在spring mvc的场景下,每次使用线程处理完一个请求,就在afterCompletion里清掉线程里的ThreadLocal变量:

        /**
         * @author caikang
         * @date 2017/04/07
         */
        public class UserHolder {
            private static final ThreadLocal<User> userThreadLocal = new ThreadLocal<User>();
    
            public static void set(User user){
                userThreadLocal.set(user);
            }
    
            public static User get(){
                return userThreadLocal.get();
            }
    
            public static void remove(){
                userThreadLocal.remove();
            }
        }
    
        /**
         * @author caikang
         * @date 2017/04/07
         */
        public class UserInterceptor extends HandlerInterceptorAdapter {
            @Override
            public boolean preHandle(HttpServletRequest request,
                HttpServletResponse response, Object handler) throws Exception {
                UserHolder.set(new User());
                return true;
            }
    
            @Override
            public void afterCompletion(HttpServletRequest request,
                HttpServletResponse response, Object handler, Exception ex) throws Exception {
                UserHolder.remove();
            }
        }
    

    通常,我们需要 保证作为key的TL_INT类型能够被全局访问到,同时也必须 保证其为单例,因此,在一个类中将其设为static类型便成为了惯用做法。

    线程池

    使用了线程池,可以达到“线程复用”的效果。但是归还线程之前记得清除ThreadLocalMap,要不然再取出该线程的时候,ThreadLocal变量还会存在。这就不仅仅是内存泄露的问题了,整个业务逻辑都可能会出错。

    解决方法参考:

    /**
     * Method invoked upon completion of execution of the given Runnable.
     * This method is invoked by the thread that executed the task. If
     * non-null, the Throwable is the uncaught {@code RuntimeException}
     * or {@code Error} that caused execution to terminate abruptly.
     *
     * <p>This implementation does nothing, but may be customized in
     * subclasses. Note: To properly nest multiple overridings, subclasses
     * should generally invoke {@code super.afterExecute} at the
     * beginning of this method.
     *
    ... some deleted ...
     *
     * @param r the runnable that has completed
     * @param t the exception that caused termination, or null if
     * execution completed normally
     */
    protected void afterExecute(Runnable r, Throwable t) { }
    

    override {@link ThreadPoolExecutor#afterExecute(r, t)}方法,对ThreadLocalMap进行清理,比如:

    protected void afterExecute(Runnable r, Throwable t) { 
        // you need to set this field via reflection.
        Thread.currentThread().threadLocals = null;
    }
    

    参考:https://stackoverflow.com/a/30328722/7676237

    附:强引用-软引用-弱引用

    • 强引用:普通的引用,强引用指向的对象不会被回收;
    • 软引用:仅有软引用指向的对象,只有发生gc且内存不足,才会被回收;
    • 弱引用:仅有弱引用指向的对象,只要发生gc就会被回收。

    看一个例子就明白强引用、软引用、弱引用的区别:

    package example.reference;
    
    import java.lang.ref.SoftReference;
    import java.lang.ref.WeakReference;
    
    /**
     * @author liuhaibo on 2018/03/06
     */
    public class WeakRefDemo {
    
        public static void main(String... args) {
    
            // all these objects have a strong reference
            Object a = new Object();
            Object b = new Object();
            Object c = new Object();
    
            // other references to these objects
            Object strongA = a;
            SoftReference<Object> softB = new SoftReference<>(b);
            WeakReference<Object> weakC = new WeakReference<>(c);
    
            // free the former strong references to these objects:
    
            // there is still a strong reference(strongA) to the first object
            a = null;
            // only a soft reference(softB) refers to the second object
            b = null;
            // only a weak reference(weakC) refers to the third object
            c = null;
    
            System.out.println("Before gc...");
            System.out.println(String.format("strongA = %s, softB = %s, weakC = %s", strongA, softB.get(), weakC.get()));
    
            System.out.println("Run GC...");
    
            System.gc();
    
            // object with only soft reference will be cleaned only if memory is not enough: 用来做缓存很不错
            // object with only weak reference will be cleaned after a gc operation:
            System.out.println("After gc...");
            System.out.println(String.format("strongA = %s, softB = %s, weakC = %s", strongA, softB.get(), weakC.get()));
        }
    }
    
    

    Output:

    Before gc...
    strongA = java.lang.Object@3af49f1c, softB = java.lang.Object@19469ea2, weakC = java.lang.Object@13221655
    Run GC...
    After gc...
    strongA = java.lang.Object@3af49f1c, softB = java.lang.Object@19469ea2, weakC = null
    
    展开全文
  • 今天写了个样例程序,程序主要是动态创建一个类的对象,存入list链表中,然后再把链表中的对象delete掉回收内存,理论上并不应该会产生内存泄露,但是从现象上来看确实是发生了内存泄露。程序启动后我分别在“创建...
  • 使用Xcode和Instruments调试解决iOS内存泄露

    万次阅读 多人点赞 2012-11-28 15:05:15
    虽然iOS 5.0版本之后加入了ARC机制,由于相互引用关系比较复杂时,内存泄露还是可能存在。所以了解原理很重要。 这里讲述在没有ARC的情况下,如何使用Instruments来查找程序中的内存泄露,以及NSZombieEnabled设置...
  • 最近朋友推荐了一篇关于内存溢出与内存泄漏的文章,感觉写的还不错,于是便在网上搜索了一番,对这块进行了加固,发现自己之前写的代码也存在一些内存泄漏的风险,所以弄懂内存泄漏与内存溢出是很有利于我们提高代码...
  • Android 内存泄露问题

    2014-12-08 07:32:34
    我的问题是:如果业务还没有进行完,Activity被销毁了,那么会不会出现内存泄露。 我的理解是:这个Runnable对象持有Activity的引用,在线程还没运行关闭的时候,Activity被销毁的话,是不能被回收的。 如果真的这样...
  • ThreadLocal内存泄露

    万次阅读 2018-09-10 17:14:16
    内存泄漏memory leak:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。 内存溢出 out of memory:没内存可以分配给新的对象了。 我们...
  • Android内存泄露

    2017-01-18 10:08:16
    本篇博客主要是记录一下Android内存泄露相关的问题。 网上有很多介绍内存泄露的文章,自己摘取了一些比较有价值的内容, 同时增加了一些自己的理解。
  • 内存泄露问题

    千次阅读 2011-10-26 22:50:26
    做iphone开发后,刚开始的时候总是内存泄露。因为ios会把不再用到的对象自动释放掉,我再次访问的时候已经不再内存里面了,就会出现EXC_BAD_ACCESS错误。   所以在要保留对象是要retain一下,记得release   ...
  • 我写了个DLL用来读取Excel表格数据,在DLL里定义了一个函数 ...运行结果就是会存在内存泄露问题,而且这个问题时隐时现, 请问各位存在,结构体数组怎样才能正确传参而不会产生内 存泄露?我上面的写法是否有什么问题?
  • 这几天使用kotlin写一个项目,用到handler,然后提醒提警告 This Handler class should be static or leaks might occur...... I wrote that debugging code because of a couple of memory leaks I ...
  • 我用的是dll, 一个进程WriteFileMap写入,另一个进程ReadFileMap,WriteFileMap每写入一次内存就增加大概1兆,知道报错〖8〗-存储空间不足,无法处理此命令。求大神,是不是哪里写的有问题 MT4_EXPFUNC wchar_t* __...
  • 内存泄露调试

    万次阅读 2015-08-01 16:58:42
    内存泄露调试(Memory Leak Debug) 一、概述内存泄露产生原因存在多种,但常见分类如下: 1. 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。 2.偶发性内存泄漏。...
  • ios alterview内存泄露

    2015-11-28 10:17:06
    请教各位大师两个问题,alterview已经releas了,为何还会出现内存泄露(并且retaincount=3)? alterview内存泄露问题该如何解决(尝试过用alterviewController,也存在内存泄露问题,ARC下也有泄露)? 附:我的xcode...
  • JAVA 内存泄露详解(原因、例子及解决)

    万次阅读 多人点赞 2016-05-05 20:24:58
    Java的一个重要特性就是通过垃圾收集器(GC)自动管理内存的回收,而不...理论上Java中所有不会再被利用的对象所占用的内存,都可以被GC回收,但是Java也存在内存泄露,但它的表现与C++不同。 JAVA 中的内存管...

空空如也

1 2 3 4 5 ... 20
收藏数 27,077
精华内容 10,830
关键字:

内存泄露