您的位置:首页 > 其它

JVM(一)

2015-12-22 22:40 218 查看

数据类型

java虚拟机可以操作的数据类型有两类:原始类型和引用类型,对应地,有原始值和引用值两种类型的数值。

基本类型包括数值类型、boolean和returnAddress;引用类型包括类类型、接口类型、数组类型。

returnAddress指向一条虚拟机指令的操作码,程序运行期间无法改变returnAddress类型的值。java虚拟机不提供操作Boolean类型的字节码指令,程序在编译后boolean类型转化成了int类型操作。

运行时数据区

有的数据区随着虚拟机进程启动而存在,有的则依赖用户线程的启动,随着线程结束而销毁。

程序计数器program counter register

字节码解释器通过改变计数器的值来选取下一条需要执行的字节码指令。pc寄存器的大小至少应该能够存放一个returnAddress类型的数据。

java虚拟机的多线程是通过线程轮流切换并分配处理器时间片的方式来实现,为了线程切换后能恢复到正确的执行位置,每条线程都保存一个独立的程序计数器。如果线程正在执行一个java方法,计数器记录的是正在执行的虚拟机字节码指令的地址,如果执行的是native方法,计数器则为空。

此内存区域是java虚拟机中没有规定任何OutofMemoryError情况的区域。

虚拟机栈VM Stack

每个java虚拟机线程都有自己的java虚拟机栈,虚拟机栈包括局部变量表、操作数、动态链接等。

每个方法被执行的时候都会创建一个栈帧,虚拟机使用局部变量表来完成方法调用时的参数传递,局部变量表的长度在编译期就决定了并存储在类和接口的字节码中,一个局部变量可以保持一个类型为boolean、byte、char、short、float、reference和returnAddress的数据,两个局部变量可以保存一个类型为long和double的数据。

栈帧中包含一个指向运行时常量区的引用支持当前方法的动态链接。

如果线程请求分配的栈容量超过虚拟机允许的最大容量时,将会抛出一个StackOverflowError异常,如果虚拟机栈可以动态扩展,但没有足够的内存或者新线程没有足够的内存创建对应的虚拟机栈,抛出OutofMemoryError异常。

本地方法栈

本地方法栈为虚拟机使用到的native方法服务。

java堆

java堆是被所有线程共享的一块内存区域,用于存放对象实例,几乎所有的对象实例都在这里分配内存。

Gc基本采用的是分代收集算法,java堆可以细分为:新生代和老年代。

方法区

方法区也是各个线程共享的内存区域。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载。

运行时常量池

运行时常量池是方法区的一部分,class中的常量池用于存放编译期生成的各种字面量和符号引用,这部分信息在类加载后存放在方法区的运行时常量池中。

常量池具有动态性,java并不要求常量一定在编译时产生,运行期间也可以将新的常量放入池中。

直接内存

直接内存并不是虚拟机数据区的一部分。NIO类使用一种基于通道与缓冲区的I/O方式,利用native函数库直接分配堆外内存,然后通过存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。

访问对象

java虚拟机规范只规定reference类型是一个指向对象的引用,不同的虚拟机实现的对象访问会有所不同,主要方法有使用句柄和直接指针。

1.使用句柄,java堆划出一块内存作为句柄池,reference中存储的是对象的句柄地址,而句柄中包含了对象实例数据(java堆)和类型数据(方法区)的具体地址信息。这样,reference中存储的是固定的句柄地址,gc中对象被移动时只会改变句柄中的实例数据指针。

2.使用直接指针,reference中直接存储的就是对象地址,但是java堆必须考虑如何放置访问类型数据的信息。这种方法速度更快。

字节码指令

java虚拟机指令为一个字节长度。

java虚拟机对于宽花类型直接支持,不需要指令执行,包括:

int类型到long、float或者double类型

long类型到float、double类型

float类型到double类型

窄化类型转换可能会造成精度丢失。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: