3. 深入了解java内存释放机制,为什么不用像c一样手动free指针?(阅读文档后的个人总结)
首先需要了解堆跟栈的概念。栈是一种先进后出数据结构,像是一个封口的瓶子存储数据,而且栈是一种连续的存储结构,而堆不是连续的存储结构,而是一种树状结构,通过指针分辨。堆栈放在一起来指一般程序运行时候的内存,但是实际上,堆栈是不一样的概念。
参考
http://c.biancheng.net/c/stack/
理解:
在程序中,栈是先进后出的数据结构,而堆则是一种特殊的完全二叉树,堆是一种经过排序后的树形结构,像是一个小土堆。
在内存分配时,栈跟堆实质上就是存储的空间,不过栈一般由系统自己分配,并且是栈的存储空间一定是连续的且一般比较小,而堆内存的存储空间不一定连续且比较大。这也就是为什么栈的存取是更快。
在java中,堆栈的分配都是由程序自动实现,而在c中堆的分配是由程序员手动分配以及释放,所以十分灵活但也相对复杂,可能造成内存泄露(我的理解是某一部分内存分配了但没释放导致一直处于占用状态而无法被重复利用)。而java中的垃圾(规定没有任何引用指向这部分资源则就是垃圾,就像是c中单链表丢失了头指针,那么你就没办法再读链表的数据)会在某一不确定时间被jvm自动释放。
提到这里,我目前的理解是jvm像是java的操作系统,其中有一些内置的功能来管理java程序减少对于底层的管理,保障了系统的安全性。
这也就可以反映为什么java占用的内存往往远大于c。
由于之前也写过类似java中堆栈区的内容,当时理解也比较浅,在阅读完上面链接的文档后,我需要额外补充一下。
我们大致知道java中基础数据类型(值类型)包括String这种不可变的数据类型是可以保存在栈区的,而为什么这些数据类型可以保存在栈区,就是因为他们是固定大小的数据类型,符合栈区的存储数据的规则,不会导致栈溢出。
同时 static声明的静态变量和全局变量是保存在静态存储区(在java中这个原来保存在方法区,同时也保存了类信息和方法信息等等,常量池就保存在这里面,后来这个有所变更)的,静态存储区是一个独立的存储区,不同的是全局变量是可以跨文件的,而静态变量是不可能跨文件的。且静态变量的生命周期由被声明的函数而定。
堆栈之所以分开,实质上就是充分利用堆栈各自的结构,能够确定大小且需要多次访问且公共的数据放在栈,不能确定大小且独立的放在堆且同时在栈中有指向这部分数据的引用。