Java 堆

Java 程序创建一个类的实例或者数组时,都在堆中为新的对象分配内存。虚拟机中只有一个堆,所有的线程都共享它。
     1
、垃圾收集(Garbage Collection
    
垃圾收集是释放没有被引用的对象的主要方法。它也可能会为了减少堆的碎片,而移动对象。在Java 虚拟机的规范中没有严格定义垃圾收集,只是定义一个Java 虚拟机的实现必须通过某种方式管理自己的堆。详情参见第九章“Garbage Collection”
     2
、对象存储结构(Object Representation
     Java
虚拟机的规范中没有定义对象怎样在堆中存储。每一个对象主要存储的是他的类和父类中定义的对象变量 。对于给定的对象的引用,虚拟机必须能很快的 定位到这个对象的数据 。另为,必须提供一种通过对象的引用方法对象数据的方法,比如方法区中的对象的引用,所以一个对象保存的数据中往往含有一个某种形式指向方法区的指针。
    
一个可能的堆的设计是将堆分为两个部分:引用池和对象池 。一个对象的引用就是指向引用池的本地指针。每一个引用池中的条目都包含两个部分:指向对象池中对象数据的指针和方法区中对象类数据的指针 。这种设计能够方便Java 虚拟机堆碎片的整理。当虚拟机在对象池中移动一个对象的时候,只需要修改对应引用池中 的指针地址。但是每次访问对象的数据都需要处理两次指针。     

     另一种堆的设计是:一个对象的引用就是一个指向一堆数据和指向相应对象的偏移指针。 这种设计方便了对象的访问,可是对象的移动要变的异常复杂。

不管虚拟机的实现使用什么样的对象表示法,很可能每个对象都有一个方法表 ,因为方法表加快了调用实例方法时的效率 ,从而对Java 虚拟机实现的整体性能起着非常重要的正面作用。

如下一种方案:每个对象的数据都包含一个指向特殊数据结构的指针,这个数据结构位于方法区,包括两部分:一个指向方法区对应数据的指针和次对象的方法表。  
     
方法表是个指针数组,其中每一项都是一个指向 实例方法数据 的指针,实例方法可以被那类的对象调用,方法表指向的实例方法数据包括以下信息:此方法的操作数栈和局部变量区的大小,此方法的字节码,异常表。  
      
堆 上的对象数据中还有一个逻辑部分,那就是对象锁, 这是一个互斥对象。虚拟机中的每个对象都有一个对象锁,它被用于协调多个线程访问同一个对象时的同步。在任何时刻,只能有一个线程拥有这个对象锁,因此只有这个线程才能访问该对象的数据,此时其他希望访问这个对象的线程只能等待,直到拥有对象锁的线程释放 锁。
 
      
很多对象在其整个生命周期内部都没有被任何线程加锁,在线程实际请求某个对象锁之前,实现对象锁所需要的数据是不必要的。
 
      
除了实现锁所需要的数据外,每个Java 对象逻辑上还与实现等待集合wait set )的数据相关联。锁是用来实现多个线程对共享数据的互斥访问的,而等待集合是用来让多个线程为完成一个共同目标而协调工作的。等待集合由等待方法和通知方法联合使用。
 
      
最后一种数据类型,可以作为堆中某个对象映像的一部分,是与垃圾收集器有关的数据。垃圾收集器必须跟踪程序引用的每个对象,这个任务不可避免地要附加一些数据给这些对象,数据的类型要视垃圾收集使用的算法而定。除了标记对象的引用情况外,垃圾收集器还要区分对象是否调用了终结方法
 
    
当程序试图将一个对象转换为另一种类型时,虚拟机需要判断这种转换是否是这个对象的类型,或者是他的父类型。当程序适用instanceof 语句的时候也 会做类似的事情。当程序调用一个对象的方法时,虚拟机需要进行动态绑定,他必须判断调用哪一个类型的方法。这也需要做上面的判断。

    
无论虚拟机实现者使用哪一种设计,他都可能为每一个对象保存一个类似方法列表的信息。因为他可以提升对象方法调用的速度,对提升虚拟机的性能非常重要,但是虚拟机的规范中比没有要求必须实现类似的数据结构。一个对象引用相关联的所有的数据结构,包括:
          1
)、一个指向类型数据的指针
          2
)、一个对象的方法列表。 方法列表是一个指向所有可能被调用对象方法的指针数组。方法数据包括三个部分:操作码堆栈的大小和方法堆栈的本地变量区;方法的字节码;异常列表。
    
垃圾收集也需要堆中的对象是否被关联的信息。Java 虚拟机规范中指出垃圾收集一个运行一个对象的finalizer 方法一次,但是容许 finalizer 方法重新引用这个对象,当这个对象再次不被引用时,就不需要再次调用finalize 方法。所以虚拟机也需要保存finalize 方法 是否运行过的信息。
     3
、数组的保存(Array Representation
Java 中,数组是一种完全意义上的对象,他和对象一样保存在堆中、有一个指向Class 类实例的引用。所有同一维度和类型的数组拥有同样的Class ,数组的长度不做考虑。 对应Class 的名字表示为维度和类型。比如一个整型数据的Class“[I” ,字节型三维数组Class 名为“[[[B” ,两维对象数据 Class 名为“[[Ljava.lang.Object”

多维数组被表示为数组的数组,数组必须在堆中保存数组的长度,数组的数据和一些对象数组类型数据的引用。通过一个数组引用的,虚拟机应该能够取得一个数组的长度,通过索引能够访问特定 的数据,能够调用 Object 定义的方法。 Object 是所有数据类的直接父类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值