Java非阻塞内存分配

时间:2009-07-24 11:04:01

标签: java jvm memory-management

我在某处读过java可以为大约12个机器指令中的对象分配内存。这对我来说非常令人印象深刻。据我所知,JVM使用的一个技巧是在块中预分配内存。这有助于最大限度地减少对操作系统的请求数量,这是非常昂贵的,我想。但即便是CAS操作也可能在现代处理器上花费多达150个周期。

那么,有没有人可以解释java中内存分配的实际成本以及JVM用于加速分配的技巧?

3 个答案:

答案 0 :(得分:21)

JVM为每个线程(TLA或线程局域)预先分配一个内存区域。 当一个线程需要分配内存时,它将在该区域内使用“Bump the pointer allocation”。 (如果“自由指针”指向地址10,并且要分配的对象大小为50,那么我们只是将空闲指针碰到60,并告诉线程它可以使用10到59之间的内存作为对象) 。

答案 1 :(得分:3)

最好的技巧是世代垃圾收集器。这使堆保持未分段,因此分配内存会增加指向可用空间的指针并返回旧值。如果内存耗尽,垃圾收集复制对象并以这种方式创建一个新的未分段堆。

由于不同的线程必须通过指向可用内存的指针进行同步,如果增加它,它们会预先分配块。所以一个线程可以分配新内存,而不需要锁定。

所有这些都在此处详细解释:http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

答案 2 :(得分:2)

JVM没有单个内存分配器。 IIRC正确地说Sun的JVM和IBM的管理内存不同。然而,一般来说,JVM的运行方式是它最初将分配一块内存,这个段足够小,可以存放在处理器缓存中,使得所有访问速度极快。

当您在应用程序内部创建对象时,对象将从此段中获取内存。段内的对象分配只是指针算术。

最初进入新鲜段的偏移地址将为零。分配的第一个对象将具有零的“地址”(实际上是该段的偏移量)。当您分配对象时,内存管理器将知道对象有多大,在段内分配那么多空间(比方说16个字节),然后将它的“偏移地址”增加一定量,这意味着内存分配速度非常快,它只是指针算术。

Sun在这里有一份白皮书http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf IBM过去在ibm.com/developerworks上有很多东西