您的位置:首页 > 其它

简单谈谈我对JVM内存管理的理解(2)

2014-09-08 21:49 239 查看
 “简单谈谈我对JVM内存管理的理解(1)“里面对jvm虚拟机运行时数据区进行了一些阐述。在这一篇里,我简单谈谈在虚拟机运行过程中,虚拟机是怎么对内存进行管理的。但是这一部分,不包括垃圾回收相关的介绍。下面我们就开始。

首先就是分配空间。前面的介绍已经说明了,空间分配有两种方式,一种是指针碰撞的方式。另一种是通过维护一份内存空闲列表的方式。但是不管用哪种方式,都不能保证分配的原子性。在非常频繁的内存分配过程中,如何保证分配操作的原子性,确实是一项挑战。我简单介绍两种方法,但具体哪种虚拟机使用的是哪种方案。这个就各不相同了。一种方法是通过失败重试的方式,保证内存分配过程中的原子性。另外一种是采取TLAB的方式,就是为每个线程单独分配一块空闲的内存,当线程需要内存时,从本地内存中获取。这就是分配内存的基本模式。

说完了分配空间,在说说空间的使用。内存过程中在使用过程中,主要被分为三个部分。一部分是对象头,在该部分,主要存储对象本身的信息。如gc分代年龄,哈希值,锁状态等并且该部分的存储是按照bit位存储的,目的是为了把大量信息存储在有限的空间内。第二部分为实例数据。实例数据存储的是创建的实例的主体部分,该部分控制的内存也是很大的,所以该部分对内存的管理是有策略的。会将长度相同的基本数据类型放在一起,例如将double和long类型放在一起,将byte类型和boolean类型放在一起。这样做,主要是为了节省空间,避免发生空位补齐。

最后说一下对齐填充,很多虚拟机对空间的要求,就是内存的起始地址必须是8的整倍数(原因不再赘述)。所以,如果内存中有不是8的整倍数的内存,虚拟机会自动补齐,这部分只是为了占位,并没有真是用途。

上面介绍了关于虚拟机对内存的分配和存储结构。下面说说在访问过程中,虚拟机是如何寻找到存储在内存中的资源的。

虚拟机在运行过程中,会有多个线程同时运行,每个线程对应到自己的一个栈(前一篇已经阐述过了),每个栈只记录进入该栈的方法的一部分信息。这些信息中的一部分,能够帮助jvm寻找到该方法对应在堆中分配的资源(这一块比较绕)。因为程序的运行顺序,是由栈决定的(栈的工作顺序)。但是运行过程中需要的大部分数据,并没有存在于栈内,栈内存储的只是能够映射到堆内存中的一些“reference”。

映射的方式,有两种方式。一种是直接指针访问,我感觉就像C++中的指针引用。这种方式很直接,最大的优势就是快,在java效率一直备受诟病的环境下,这种方式有很大的市场的。另外一种方式是“句柄式”,其实我是很讨厌“句柄”这个词的。我真的不知道是谁翻译了这个词。我在阅读Thinking in java的时候(那时候刚刚接触java),句柄给我带来了很大困扰。我不知道这个东西是什么东西。后来一气之下换成英文的,当看到reference的时候,我一下就明白了,句柄这个词,你得先知道他代表的是什么意思,才能理解他的用法。句柄的方式,就是在堆内部建立一个句柄池,每个方法以及他对应的数据,都通过这个句柄区来关联维护,而栈内只需要维护一个指向句柄池的reference即可。采用这种方式,速度要慢于直接指针访问的方式,但是这种方式,在管理方面,由于直接指针引用方式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: