内存泄漏

一文搞懂V8引擎的垃圾回收

女生的网名这么多〃 提交于 2019-12-12 09:27:29
引言 作为目前最流行的JavaScript引擎,V8引擎从出现的那一刻起便广泛受到人们的关注,我们知道,JavaScript可以高效地运行在浏览器和Nodejs这两大宿主环境中,也是因为背后有强大的V8引擎在为其保驾护航,甚至成就了Chrome在浏览器中的霸主地位。不得不说,V8引擎为了追求极致的性能和更好的用户体验,为我们做了太多太多,从原始的 Full-codegen 和 Crankshaft 编译器升级为 Ignition 解释器和 TurboFan 编译器的强强组合,到隐藏类,内联缓存和 HotSpot 热点代码收集等一系列强有力的优化策略,V8引擎正在努力降低整体的内存占用和提升到更高的运行性能。 本篇主要是从V8引擎的垃圾回收机制入手,讲解一下在JavaScript代码执行的整个生命周期中V8引擎是采取怎样的垃圾回收策略来减少内存占比的,当然这部分的知识并不太影响我们写代码的流程,毕竟在一般情况下我们很少会遇到浏览器端出现内存溢出而导致程序崩溃的情况,但是至少我们对这方面有一定的了解之后,能增强我们在写代码过程中对减少内存占用,避免内存泄漏的主观意识,也许能够帮助你写出更加健壮和对V8引擎更加友好的代码。本文也是笔者在查阅资料巩固复习的过程中慢慢总结和整理出来的,若文中有错误的地方,还请指正。 1、为何需要垃圾回收 我们知道

Spring提供的IntrospectorCleanupListener监听器解析

浪尽此生 提交于 2019-12-12 05:09:11
Introspector作用及影响 在分析IntrospectorCleanupListener之前,先了解一下Introspector。Introspector是JDK中java.beans包下的类,它为目标JavaBean提供了一种了解原类方法、属性和事件的标准方法。通俗的说,就是可以通过Introspector构建一个BeanInfo对象,而这个BeanInfo对象中包含了目标类中的属性、方法和事件的描述信息,然后可以使用这个BeanInfo对象对目标对象进行相关操作。 下面看一个简单的示例会很容易明白。为了简单,Student类中只有一个name属性。 结果输出:Student{name=‘张三’} 通过查看Introspector.getBeanInfo方法的源码会发现,Introspector在构建一个BeanInfo对象的时候,会将构建的BeanInfo对象和原类缓存到一个Map中,源码如下。 通过上的代码可以得出,Introspector间接持有了BeanInfo的强引用。如果使用Introspector操作了很多类,那么Introspector将间接持有这些BeanInfo的强引用。在发生垃圾收集的时候,检测到这些BeanInfo存在引用链,则这些类和对应的类加载器将不会被垃圾收集器回收,进而导致内存泄漏。所以,为了解决这个问题

再探C++Primer (4)指针、引用、对象和内存

北城以北 提交于 2019-12-09 13:22:10
###基本内置类型和复合类型# 基本内置类型就是算数类型和空类型,算数类型包括字符、整数、布尔值、浮点数,空类型是void; 复合类型指基于其他类型定义的类型,例如指针和引用。 ###引用# 引用就是给对象起的别名,通过声明对象时在对象标识符前加‘&’符号来定义引用类型。例如:int a=100;int &b=a;则可以通过对b的操作来操作变量a; 引用本身并不是对象,只是对象的别名,在内存中没有具体的存在; 引用只与其初始化的对象绑定在一起,初始化后不能将引用绑定到其他对象上; 引用只能绑定在对象上而不能绑定在表达式或字面值常量上。 ###指针# 指针同引用近似,提供了对其他对象的间接访问; 指针是一个独立的对象,允许对指针进行赋值和拷贝,定义指针后,根据计算机位数不同在内存中占据不同的大小,例如32位计算机/32位编译器中,指针大小是4字节; 指针存储的是对象在内存中的逻辑地址; 指针可以不被初始化也可以在生命周期内指向多个对象。 ####获取对象地址、利用指针访问对象# 指针一般要求指针类型同其所指对象严格匹配 int a = 10; int *b; b = &a; //通过取地址符获取变量a地址 int c = *b; //通过解引用符获取指针b所指变量 double *d = a; //错误,指针类型同所指对象不匹配 指针可以不被初始化,通过取地址符&可以获取对象地址

由Static引起的内存泄漏问题

安稳与你 提交于 2019-12-08 11:15:50
什么是内存泄漏? 通俗地讲,就是程序在向系统申请使用内存后,在使用完以后并没有释放内存,而导致该内存一直被占用。直到程序结束,我们也无法再使用这边内存。 这里说一下遇到的一个由static关键字引起的内存泄漏问题。 通过内存泄漏检测工具,我发现我前几天写的代码中,有某一个内存泄漏发生了:某工具类一直持有某个Activity对象。 我翻了一下代码,发现是这样的: 我有某个ScreenUtil工具类,它的构造函数是这样的: private ScreenUtil (Context context) { this .context = context; ********** //其余代码省略 } 对外提供实例的方法: private static ScreenUtil instance; public static ScreenUtil getInstance (Context context) { if (instance == null ) { instance = new ScreenUtil(context); } return instance; } 也就是说,对外提供的是一个statis类型的实例,它是在我的一个自定义控件中使用的,在这个自定义控件是在一个Fragment中被使用。由于没有在Fragment被销毁的时候,将这块内存释放掉,所以产生了内存泄漏的问题。

C++内存泄漏及解决方法

巧了我就是萌 提交于 2019-12-08 11:15:25
1.首先说到c++内存泄漏时要知道它的含义? 内存泄漏(memory leak)是指由于疏忽或错误造成了程序未能释放掉不再使用的内存的情况。内存泄漏 并非指内存在物理上的消失,而是 应用程序 分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。 2.内存泄漏的后果? 最难捉摸也最难检测到的错误之一是内存泄漏,即未能正确释放以前分配的内存的 bug。 只发生一次的小的内存泄漏可能不会被注意,但泄漏大量内存的程序或泄漏日益增多的程序可能会表现出各种征兆:从性能不良(并且逐渐降低)到内存完全用尽。 更糟的是,泄漏的程序可能会用掉太多内存,以致另一个程序失败,而使用户无从查找问题的真正根源。 此外,即使无害的内存泄漏也可能是其他问题的征兆。 3.对于C和C++这种没有垃圾回收机制的语言来讲,我们主要关注两种类型的内存泄漏: (1)堆内存泄漏 (Heap leak)。对内存指的是程序运行中根据需要分配通过malloc,realloc new等从堆中分配的一块内存,再是完成后必须通过调用对应的 free或者delete 删掉。如果程序的设计的错误导致这部分内存没有被释放,那么此后这块内存将不会被使用,就会产生Heap Leak. (2)系统资源泄露(Resource Leak).主要指程序使用系统分配的资源比如 Bitmap,handle

Android Context导致的内存泄漏分析(示例代码+分析工具使用)

≯℡__Kan透↙ 提交于 2019-12-08 11:14:01
Android开发中因为有限的内存,以及防止OOM问题出现,解决内存泄漏问题将是开发者一直持续下去的工作。本文就分析了不当使用(持有)context导致的内存泄漏。 1. 为什么使用Context有可能会导致内存泄漏? 首先从context的本质谈起,context名称上代表了上下文,实质上是Application、Activity或Service的一个引用。因此如果有生命周期较长的对象,比如线程持有了一个context引用,那么在线程结束前,这个context是无法得到释放的,这也意味着context代表的activity、service无法被GC回收,这就发生了内存泄漏。 2. 来个例子 还记得屏幕旋转,会销毁当前Activity,重新创建一个新的Activity的事吗?我们就以这个操作来做泄漏内存的示例,原理是让老的Activity无法被销毁。 private static Drawable mBackgroudImage; @Override protected void on Create(Bundle state ) { super. on Create( state ); TextView label = new TextView(this);//持有context label . set Text( "演示旋转屏幕导致内存泄漏" ); if

static关键字所导致的内存泄漏问题

前提是你 提交于 2019-12-08 11:10:53
大家都知道内存泄漏和内存溢出是不一样的,内存泄漏所导致的越来越多的内存得不到回收的失手,最终就有可能导致内存溢出,下面说一下使用staitc属性所导致的内存泄漏的问题。 在dalvik虚拟机中,static变量所指向的内存引用,如果不把它设置为null,GC是永远不会回收这个对象的,所以就有了以下情况: public class SecondActivity extends Activity{ private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); SecondActivity.this.finish(); this.removeMessages(0); } }; private static Haha haha; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); haha = new Haha(); mHandler.sendEmptyMessageDelayed(0,2000); } class Haha{ } } 非静态内部类的静态引用

C++程序如何精确查找内存泄漏

大城市里の小女人 提交于 2019-12-07 09:40:35
一、前言 在Linux平台上有valgrind可以非常方便的帮助我们定位内存泄漏,因为Linux在开发领域的使用场景大多是跑服务器,再加上它的开源属性,相对而言, 处理问题 容易形成“统一”的标准。而在Windows平台,服务器和客户端开发人员惯用的调试方法有很大不同。下面结合我的实际经验,整理下常见定位内存泄漏的方法。 注意: 我们的分析前提是Release版本 ,因为在Debug环境下,通过VLD这个库或者CRT库本身的内存泄漏检测函数能够分析出内存泄漏,相对而言比较简单。而服务器有很多问题需要在线上并发压力情况下才出现,因此讨论Debug版调试方法意义不大。 二、对象计数 方法:在对象构造时计数++,析构时--,每隔一段时间打印对象的数量 优点:没有性能开销,几乎不占用额外内存。定位结果精确。 缺点:侵入式方法,需修改现有代码,而且对于第三方库、STL容器、脚本泄漏等因无法修改代码而无法定位。 三、重载new和delete 方法:重载new/delete,记录分配点(甚至是调用堆栈),定期打印。 优点:没有看出 缺点:侵入式方法,需将头文件加入到大量源文件的头部,以确保重载的宏能够覆盖所有的new/delete。记录分配点需要加锁(如果你的程序是多线程),而且记录分配要占用大量内存(也是占用的程序内存)。 四、Hook Windows系统API 方法

C++中基类的析构函数为什么要用virtual虚析构函数

倾然丶 夕夏残阳落幕 提交于 2019-12-07 07:29:33
知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定。 关于动态绑定的讲解,请参阅: C++中的动态类型与动态绑定、虚函数、多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。 示例代码讲解 现有Base基类,其析构函数为非虚析构函数。Derived1和Derived2为Base的派生类,这两个派生类中均有以string* 指向存储其name的地址空间,name对象是通过new创建在堆上的对象,因此在析构时,需要显式调用delete删除指针归还内存,否则就会造成内存泄漏。 class Base { public: ~Base() { cout << "~Base()" << endl; } }; class Derived1 : public Base { public: Derived1():name_(new string("NULL")) {} Derived1(const

C++中基类的析构函数为什么要用virtual虚析构函数

我怕爱的太早我们不能终老 提交于 2019-12-07 07:09:56
大家知道,析构函数是为了在对象不被使用之后释放它的资源,虚函数是为了实现多态。那么把析构函数声明为vitual有什么作用呢? 直接的讲, C++中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。 请看下面的代码: #include <iostream> using namespace std; class Base { public: Base() {}; //Base的构造函数 ~Base() //Base的析构函数 { cout << "Output from the destructor of class Base!" << endl; }; virtual void DoSomething() { cout << "Do something in class Base!" << endl; }; }; class Derived : public Base { public: Derived() {}; /