sherry say:
JAVA
内存
:
Heap
堆区
-->
对象实际存放的地方
Stack
栈区
--> Thread
独享,存放【
1
】
new
出来的对象的引用,【
2
】基本类型数据
Static
常量区
-->
Thread
共享
Heap
比
Stack
所占空间大,所以慢,与具体实现无关
Array list
与
linked list
比较:
add
:【
1
】寻址到最后一个元素(
Array
直接可以算出地址,
linked list
需要遍历所有节点),【
2
】添加元素
insert
:【
1
】寻址到指定元素,【
2
】添加新元素并移动后续元素(
Array
的需要遍历移动,
linked list
只需改动
pre
和
next
的
link
)(也可以讲
Array
的主要
cost
在于堆操作,而
linked list
基本都是栈操作)
--------------------------------------------------------------------------------------------------------------------------------------------
Answer:
理解堆区、栈区、常量区这些内存模型,是学习JVM虚拟机、垃圾回收,java线程的基础。
原理其实也是参照操作系统(windows、linux)设计的。
以下说的没啥问题了,记得堆区也是线程共享的。
堆区的操作会比栈区操作慢,也有很多原因了,上次没讲全,一时想不起那么多。
1 空间比栈区大得多,寻址费时,当时这是最基本的
2 堆区的内存操作同时伴随着垃圾回收,本身就很耗时,算法也复杂,比如划分新生代老年代,判断对象是否需要回收,如果是full GC,甚至整个系统都会停顿
#垃圾回收只针对堆
3 除了对象回收即垃圾回收,对象初始化的做法也很不同,
栈区都是个4字节的对象引用,比如程序进入了某个函数,方法内多一个引用就多push一个4字节的指针(引用)进栈,如果程序出了函数,局部变量的引用就全部弹出,很好的利用了后进先出的特性。这里也要注意,栈区的操作是利用了栈这个数据结构做的一系列内存操作。
堆区则要在内部根据不同对象大小选择初始头地址,占用空间比较大的对象为了保证内存连续,可能还要调整其他对象的存储位置,如果新生代放不下的对象要放到老年代,新生代存在时间久了也要放到老年代等等
垃圾回收我们肯定还要另外从头讲的,但简单来说,就是当某个对象已经不使用,栈区已经把对象引用弹出去了,这时候堆区通过计数的方式,清算当前对象是否有引用,没有的就回收,通过计时的方式,如果一段时间依然存在引用,则进入老年代。
所以堆区复杂很多了吧。
list的总结已经挺到位了,理解得不错。
补充下,arraylist是内存连续的,而linkedList是链式结构,散的。
insert你写的arraylist要遍历移动,我知道你的意思啦,你想表达的是后移操作,更专业的说法是内存relloc,意思是重新分配内存,因为以我们人类的思维来说这是后移,对于计算机来说,这么大块内存,每个值都重新写,并可能要扩容,对于计算机是一个relloc操作,这样的操作都比较花费时间