运行时内存异常
在java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError异常的可能
在java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError异常的可能
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及各自的创建和销毁时间,有的区域随虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁
Java的编译过程可以分为两个阶段,首先是将.java文件编译为.class文件的过程,称为前端编译,比如javac;然后在运行期,可能即时编译器(JIT)又会将字节码转变为本地机器码,比如HotSopt的C1、C2编译器,或者Graal编译器。
对于优化处理,Java虚拟机团队选择将性能优化的措施全部集中在运行期的即时编译器中,以便让那些不是由 javac 产生的 Class 文件也能享受到性能优化的好处,至于 javac 中则做了一些针对Java语言编码过程的优化,用来降低开发者的编码复杂度、提高编码效率。可以这样认为,即时编译器在运行期的优化过程,支撑了程序执行效率的不断提升,而javac在编译期的优化过程,则支撑了开发者的编码效率和语言使用者的体验。
Java虚拟机的字节码指令集自Sun公司推出第一款Java虚拟机至今,二十余年间只新增过一条指令,它就是随着JDK 7一起发布的 invokedynamic 指令。这条新增指令是JDK 7的项目目标:实现动态类型语言支持而进行的改进之一,也是为JDK 8中可以顺利实现 Lambda 表达式而做的技术储备。
Java虚拟机以方法作为最基本的执行单元,而栈帧则是用于支持虚拟机进行方法调用和方法执行背后的数据结构,它也是虚拟机运行时数据区中的虚拟机栈的栈元素。
Java虚拟机的指令由一个字节长度(0 ~ 255)、代表着某种特定操作含义的数字(操作码),以及其后跟随的零至多个参数(操作数)构成。由于Java虚拟机采用面向操作数栈而不是面向寄存器的架构,所以大多数指令都不包含操作数,只有一个操作码,指令参数都存放在操作数栈中。
采用一个字节来代表操作码,也是为了尽可能获得短小精干的编译代码,这种追求尽可能小数据量、高传输效率的设计,也是由于Java语言设计之初,主要面向网络、智能家电的技术背景所决定的,并一直沿用至今。