Java的堆栈和堆

堆栈和堆通常与对象的创建和生命期一起考虑

Java中使用对象时,最关键的问题之一是它们的生成和销毁方式。

每一个对象为了生存都需要资源,尤其是内存。

当我们不需要时,它必须被清理掉,使其占有的资源可以被释放和重用。

在相对简单的编程情况下,怎么清理对象看起来似乎不是什么挑战。然而,你很可能遇到相对复杂的情况。

例如,假设你处理完某个对象后,系统某个其他部分还在处理它,那么何时才能知道可以销毁了呢?

在其他许多场合也会遇到这种问题,并且在必须明确删除对象的编程系统中(例如C++),此问题会变得十分复杂。

(一)那么,对象的数据位于何处?

C++认为,效率控制,是最重要的议题。

所以,C++给予程序员选择的权力。

第一种方式:

为了追求最大的执行速度,对象的存储空间和生命周期可以在编写程序时确定。

这可以通过将对象置于堆栈stack(自动变量或限域变量)或静态存储区域内来实现。

这种方式将存储空间分配和释放放置于优先考虑的位置,某些情况下这样控制非常有价值,但也牺牲了灵活性。

因为,必须在编写程序时知道对象确切的数量、生命周期和类型。

第二种方式(动态方式):

在堆heap的内存池种动态的创建对象。

对于这种方式,直到运行时,才知道需要多少对象。对象的生命周期、具体类型都只能在程序运行时相关代码被执行到的那一刻,才能知晓确定。

如果需要一个新对象,可以在需要的时刻,直接在堆中创建。这种方式,因为存储空间是在运行时被动态的管理的,所以需要大量的时间在堆种分配存储空间。这可能要远远大于在堆栈种创建存储空间的时间。

而在堆栈种创建存储空间和释放存储空间通常各需要一条汇编指令即可,分别对应将栈顶指针向下移动和向上移动。

创建堆栈存储空间的时间依赖于存储机制的设计。

动态方式有一个一般性的逻辑假设:

对象趋向于变得复杂,所以,查找和释放存储空间的开销,不会对对象的创建造成重大冲击。

动态方式所带来的更大的灵活性,正是解决一般化编程问题的要点所在。

Java采用的正是动态内存分配方式。每当 需要创建新对象时,就要使用new关键字来构建此对象的动态实例。

(二)怎么控制对象的生命周期?

首先,我们应该知道,对于允许在堆栈stack上创建对象的语言,编译器可以确定对象存活的时间,并可以自动销毁。

但是,假如在堆heap上创建对象,编译器会对它的生命周期一无所知。

在像C++这样的语言中,必须通过编程方式来确定何时销毁对象,这可能会因为不能正确处理而导致内存泄漏

Java提供了“垃圾回收器”机制。可以自动发现对象何时不再被使用,并继而销毁它。该垃圾回收器减少了所必须考虑的议题和必须编写的代码。

更重要的是,它提供了更高层的保障,可以避免暗藏的内存泄漏问题。

注意,垃圾回收器机制同所有对象都是继承自单根基类Object以及只能以一种方式创建对象(在堆上创建)这两个特性结合起来,

使得Java编程比C++要简单的多,所要做出的决策和要克服的障碍也要少得多。

备注:

在Java中,每一个线程包含一个栈,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),并且是私有的,不能被其他堆栈访问。

但jvm只有一个堆区,被所有线程共享,存放对象本身。

猜你喜欢

转载自www.cnblogs.com/hoanfir/p/9258625.html
今日推荐