众所周知,java和c++不一样,在java中,对象只能用new操作符在heap中分配,不可以象c++一样在栈上分配。
一般来说,在堆上分配的效率要低于栈,。例如堆是全局的,在多线程程序中要使用锁来进行同步,不巧的是,绝大部分的java程序都是多线程的。另一方面,随着对象的生成和销毁,堆上会产生碎片,需要一个或多个freelist来维护,这样也造成额外的开销,以及空间利用的低效。
但这是一般c程序员理解的heap管理机制,也因此有c程序员指责java的内存管理效率低下。其实在jvm的实现中,它会用自己的方式来管理堆,增强java的效率。以Hotspot为例,每个线程都会拥有一段自己的空间称为TLAB(Thread Local Alloc Buffer),这块空间因为属于线程独有,所以在其中分配对象不需要加锁,其实和栈一样,分配对象只要将一个指针增加sizeof(object)即可。如果对象太大超出了tlab的剩余空间,此时有多种选择,
在heap的share空间中分配,
重新分配一块tlab
在old generation中分配
触发gc,释放已有空间。
具体选择何种方式由内存的利用情况和jvm的内存管理策略决定。由多个参数可以进行调整。所以在绝大部分情况下(〉90%),jvm中对象的分配和栈一样高效。
关于对象的释放,就是java中著名的gc来负责了,关于gc的介绍多如牛毛,而且其中的方式和策略层出不穷,这片文章就不介绍了。
从上面的介绍可以看出,这种方式可以加速对象的分配,但对释放不能作到象stack那样高效,其实有很多对象只是生存期很短的临时对象,如何识别这些对象并在tlab中更有效的释放应该是jvm可以进一步优化的方向。据我所知,jdk6的jvm已经使用了相关的技术。
posted on 2007-10-01 23:10
白色天堂 阅读(477)
评论(0) 编辑 收藏