基础知识:在java虚拟机中有2种数据类型:基本类型和引用类型。
基本类型包括:
(1) 数值类型(byte,short,char,int,long,float,double) ,注:在jvm中boolean类型用int来表示,boolean数组用byte数组来表示。(在栈中byte,short,char都被转换成int型来处理,后面会提到。由此我想到一个java面试题:定义一个包含switch……case……语句的函数,问传入什么样的参数是合法的。java的switch case语句只支持int和能转换成int的类型,所以byte、short、char、int都可以传入switch……case……函数。在C#中switch……case……还支持字符串,曾经有段时间对这个犯浑。跑题了,呵呵)。
(2) 还有一个基本类型是returnAddress。这个类型被jvm用在实现finally时使用,开发人员本身不能使用该类型。
引用类型(Referenc):
引用类型包括三种:类类型、接口类型、数组类型(注意:数组是对象,基本数据类型数组也是对象,如int[])
一个JVM实例运行时数据区分成以下几部分:
堆(Heap):在JVM中,程序创建的所有对象和数组都存放在堆上,这是所有线程都共享的,所以对于堆上数据的访问,在必要的时候就要考虑多线程的问题了。在物理上堆没有必要是连续的地址空间。堆的大小一般可以通过-Xms -Xmx 参数来设定。
方法区:个人认为叫类数据区或许会更形象些。JVM加载的所有class都存放在方法区中,这里既包括类得结构信息还有类变量(即类中的静态变量,注意,常量--final static修饰的变量,一般在编译时就进行优化了),常量池等。方法区也是所有线程共享的。在物理上,方法区也没必要是连续的地址空间。方法区的大小可以通过-XX:PermSize -XX:maxPermSize 来设置。
栈: 每启动一个线程,jvm都会为它非配一个私有的栈,栈由栈帧组成。每执行一个方法,都会往栈中压入一个帧,它里面存放了参数、局部变量、中间运算结果等。一个帧由局部变量区、操作数栈和帧数据区组成。
(1) 局部变量区:局部变量区被组织成一个以字长为单位,从0开始的数组。int,float,reference,returnAddress占用一个字,long,double占用连续的2项。byte,char,short在存入帧前都被转换成int,当他们被重新放回堆或者方法区时,会转换回原来的类型。在访问long、double时,只需给出第一项的下标。对于实例方法(相对应静态方法而言),局部变量区第一值是指向this的 reference。
(2) 操作数栈: 顾名思义存放操作数的地方,它也是以数组的形式存在,只是以弹栈、压栈来访问。
(3) 帧数据区:除了局部变量和操作数栈外,栈帧还需要一些数据来支持常量池解析,正常方法返回以及异常派发机制。
本地方法栈:调用native方法时存放临时数据的区域。
程序寄存器:当指向java方法是,程序寄存器里的内容总是下一条将被执行的指令的“地址”,这个“地址”可以使一个本地指针,也可以是在方法字节码中的相对该方法起始指令的偏移量。如果正在执行native方法,则寄存器里的值是undefined。