运行时数据区

Java虚拟机运行时,它需要内存来存取很多东西。例如,字节码,从已经装载的class文件中得到的其他信息,程序创建的对象,传递给方法的参数,返回值,局部变量,已经运算的中间结果等。Java虚拟机把这些数据都组织到几个“运行时数据区”,以便于管理,主要包括方法区、堆、Java栈、PC寄存器、本地方法栈
 

 

方法区

 

      Java虚拟机中,关于被装载的类型的信息存储在一个逻辑上被称为方法区的内存中。当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入这个class文件--------一个线性二进制数据流--------然后把它传输到虚拟机中。紧接着虚拟机提取其中的类型信息,并将这些信息存储到方法区。该类型中的类(静态)变量同样也存储在方法区中。

 

       由于所有线程都共享方法区,因此它们对方法区数据的访问必须被设计是线程安全的。比如,假设同时两个线程都企图访问一个名为Lava的类,而这个类还没有内装载入虚拟机,那么,这时应该只有一个线程去装载它,而另一个线程则只能等待。

 

       对每个装载的类型,虚拟机都会在方法区中存储一下类型信息:

 

l  这个类型的全限定名

l  这个类型的直接超类的全限定名(除了Object

l  这个类型的是类类型还是接口类型

l  这个类型的访问修饰符

l  任何直接超接口的全限定名的有序列表

除了上面的基本信息以外,虚拟机还得为每个被装载的类型存储以下信息:

 

l  该类型的常量池

l  字段信息

l  方法信息

l  除了常量以外的所有类变量

l  一个到ClassLoader的引用

l  一个到Class类的引用

 

      

指向ClassLoader的引用

 

       每个类型被装载的时候,虚拟机必须跟踪它是由启动类装载器还是由用户自定义类装载器装载的。如果是用户自定义类装载器装载的,那么虚拟机必须在类型信息中存储对该类型装载器的引用。这是作为方法表中的类型数据的一部分保存的。

 

       虚拟机会在动态连接期间使用这个信息。当某个类型引用另一个类型的时候,虚拟机会请求装载发起引用的类装载器来装载被引用的类型。这个动态连接的过程,对于虚拟机分离命名空间的方式也是至关重要的。为了能够正确执行动态连接以及维护多个命名空间,虚拟机需要在方法表中得知每个类都是哪个类装载器装载的。

 

 

 

指向Class的引用

 

对于每个被装载的类型(不管是类还是接口),虚拟机都会相应地为它在堆上创建一个java.lang.Class类的实例,而且虚拟机还必须以某种方式把这个实例和存储在方法区中的类型数据关联起来。

 

       在程序中,可以使用指向Class对象的引用。Class类中的两个方法可以得到任何已装载的类的Class实例的引用。分别是Class.forName(“”)以及Class.getClass()

 

       给出一个Class对象的引用,就可以通过Class类中的定义的方法来找出这个类型的相关信息。如果查看这些方法会很快意思到,Class类使得运行程序可以访问方法区中保存的信息。下面的是Class类中声明的方法:

 

public string getName();                     返回类的全限定名

public Class getSuperClass();        返回类型的直接超类实例(object或者接口返回null

public boolean isInterface();         判断该类型是否是接口

public Class[] getInterfaces();              返回一个Class对象数组,每个Class对象对应一个直接超类接口,如果该类型没有直接超接口,getInterfaces()返回一个0长度数组

public ClassLoader getClassLoader();    返回该类型的ClassLoader对象的引用

 

 

 

 

Java程序在运行时创建的所有类实或数组都放在同一个堆中。而一个Java虚拟实例中只存在一个堆空间,因此所有线程都将共享这个堆。

 

Java对象中包含的基本数据由他所属的类及其所有超类声明的实例变量组成。只要有一个对象引用,虚拟机就必须能够快速的定位对象实例的数据。另外,它也必须能通过该对象引用访问相应的类数据(存储于方法区的类型信息)。因此在对象中通常会有一个指向方法区的指针。

 

程序计数器

 

       每个运行中的Java程序,每一个线程都有它自己的PC寄存器,也是该线程启动时创建的。PC寄存器的内容总是指向下一条将被执行指令的饿“地址”,这里的“地址”可以是一个本地指针,也可以是在方法区中相对应于该方法起始指令的偏移量。

 

Java

 

       Java栈以帧为单位保存线程的运行状态。虚拟机只会直接对Java栈执行两种操作:以帧为单位的压栈或出栈。

 

       和方法区和堆一样,Java栈和帧在内存中也不必是连续的。帧可以分布在连续的栈里,也可以分布在堆里,或者两者兼有的。

 

       栈帧

 

       栈帧由三部分组成:局部变量、操作数栈和帧数据区。

 

       当虚拟机调用一个Java方法时,它从对应类的而类型信息中得到此方法的局部变量区和操作数栈的大小,并据此分配栈帧内存,然后压入Java栈中。

 

       局部变量:存放局部变量和方法参数

       操作数栈:线程的工作区,用来存放运算过程中的临时数据

       帧数据区:保存支持常量解析、正常方法返回以及异常派发机制的数据

 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值