常常看到一些编程语言的书上有说,程序运行过程当中,会涉及到 栈(Stack)和 堆(Heap)。尤为遇到涉及调查内存泄漏的场景时,书本会提醒让开发人员查看 堆 的状况javascript
基于上述现象,来了两个疑问:java
程序执行过程当中,为何常常会涉及到 栈 和 堆 两个数据结构,他们一般的做用是什么?c++
选用 栈 能够理解,但为何选用 堆 呢?对比其余的数据结构,在程序执行过程当中,堆 的优点是什么?编程
(资料主要来源于 stackoverflow,进行消化以及整理)数据结构
关于 堆栈,首先引入两个解释:多线程
根据上述资料可知,上述的两个疑问提到的 堆 其实都不是对应数据结构中的堆的概念,因此问题自己是不许确的~架构
至于 栈 和 堆 在程序运行过程当中起到什么样的做用,详细过程又是怎么样的,上述资料已经能够窥探一二,而其中的细节,就不是这个篇章能够容纳的了(并且不一样的系统架构,不一样的 runtime 细节上又不同),就不在这里展开细述了。并发
class HeapStats {
public:
static const int kStartMarker = 0xDECADE00;
static const int kEndMarker = 0xDECADE01;
intptr_t* start_marker; // 0
size_t* ro_space_size; // 1
size_t* ro_space_capacity; // 2
size_t* new_space_size; // 3
size_t* new_space_capacity; // 4
size_t* old_space_size; // 5
size_t* old_space_capacity; // 6
size_t* code_space_size; // 7
size_t* code_space_capacity; // 8
size_t* map_space_size; // 9
size_t* map_space_capacity; // 10
size_t* lo_space_size; // 11
size_t* code_lo_space_size; // 12
size_t* global_handle_count; // 13
size_t* weak_global_handle_count; // 14
size_t* pending_global_handle_count; // 15
size_t* near_death_global_handle_count; // 16
size_t* free_global_handle_count; // 17
size_t* memory_allocator_size; // 18
size_t* memory_allocator_capacity; // 19
size_t* malloced_memory; // 20
size_t* malloced_peak_memory; // 21
size_t* objects_per_type; // 22
size_t* size_per_type; // 23
int* os_error; // 24
char* last_few_messages; // 25
char* js_stacktrace; // 26
intptr_t* end_marker; // 27
};
复制代码
从状态类上,咱们能够看到,有针对 新生代 和 老生代 的描述:new_space_size,new_space_capcacity,old_space_size,old_space_capacity,可知 javascript 的堆内存参考过 jvm 的堆内存管理模式,以便优化内存回收的效率app
//
// Most object types in the V8 JavaScript are described in this file.
//
// Inheritance hierarchy:
// - Object
// - Smi (immediate small integer)
// - HeapObject (superclass for everything allocated in the heap)
// - JSReceiver (suitable for property access)
// - JSObject
// - JSArray
// - JSArrayBuffer
// - JSArrayBufferView
// - JSTypedArray
// - JSDataView
// - JSBoundFunction
// - JSCollection
// - JSSet
// - JSMap
// - JSDate
// - JSFunction
// - JSGeneratorObject
// - JSGlobalObject
// - JSGlobalProxy
// - JSMapIterator
// - JSMessageObject
// - JSModuleNamespace
// - JSPrimitiveWrapper
// - JSRegExp
// - JSSetIterator
// - JSStringIterator
// - JSWeakCollection
// - JSWeakMap
// - JSWeakSet
// - JSCollator // If V8_INTL_SUPPORT enabled.
// - JSDateTimeFormat // If V8_INTL_SUPPORT enabled.
// - JSListFormat // If V8_INTL_SUPPORT enabled.
// - JSLocale // If V8_INTL_SUPPORT enabled.
// - JSNumberFormat // If V8_INTL_SUPPORT enabled.
// - JSPluralRules // If V8_INTL_SUPPORT enabled.
// - JSRelativeTimeFormat // If V8_INTL_SUPPORT enabled.
// - JSSegmenter // If V8_INTL_SUPPORT enabled.
// - JSSegmentIterator // If V8_INTL_SUPPORT enabled.
// - JSV8BreakIterator // If V8_INTL_SUPPORT enabled.
// - WasmExceptionObject
// - WasmGlobalObject
// - WasmInstanceObject
// - WasmMemoryObject
// - WasmModuleObject
// - WasmTableObject
// - JSProxy
复制代码
能够看到,v8 在执行 js 过程当中,runtime 内部产生的 js 对象会继承自 HeapObject 这个类,而 HeapObject 会根据策略从 runtime 的 堆 中进行 存储、移动、释放等操做jvm
咱们也知道,javascript 的数据类型会区分 基本类型(String,Number,Boolean,Null,Undfined,Symbol) 和 引用数据类型(Object,Array,Function)
从上面的注释能够看出来,基本数据类型 并无继承自 HeapObject,在 js 的执行过程当中,它们会被记录到 栈(Stack)中,当函数执行完毕后,即从栈中退出。而引用数据类型 则继承自 HeapObject,在执行过程当中,从堆中存储,再也不被引用后,将会等待 GC 依据策略将其清理