动态类型语言支持

Java虚拟机的字节码指令集自Sun公司推出第一款Java虚拟机至今,二十余年间只新增过一条指令,它就是随着JDK 7一起发布的 invokedynamic 指令。这条新增指令是JDK 7的项目目标:实现动态类型语言支持而进行的改进之一,也是为JDK 8中可以顺利实现 Lambda 表达式而做的技术储备。

方法调用 重载 & 重写

Java虚拟机以方法作为最基本的执行单元,而栈帧则是用于支持虚拟机进行方法调用和方法执行背后的数据结构,它也是虚拟机运行时数据区中的虚拟机栈的栈元素。

字节码指令

Java虚拟机的指令由一个字节长度(0 ~ 255)、代表着某种特定操作含义的数字(操作码),以及其后跟随的零至多个参数(操作数)构成。由于Java虚拟机采用面向操作数栈而不是面向寄存器的架构,所以大多数指令都不包含操作数,只有一个操作码,指令参数都存放在操作数栈中。

采用一个字节来代表操作码,也是为了尽可能获得短小精干的编译代码,这种追求尽可能小数据量、高传输效率的设计,也是由于Java语言设计之初,主要面向网络、智能家电的技术背景所决定的,并一直沿用至今。

类 & Class对象/反射

在类加载成功之后,便以Class对象的形式保存在内存中。可以将Class对象理解成实例对象的元数据,通过Class对象中描述的类型信息,便可以创建对应的实例对象,从而进行方法调用,以及字段修改。那么,便可以通过反射根据运行时获取的类型信息来创建实例,而且可以跳过访问权限的限制访问字段和方法

类 & 加载

类加载,即把描述类的字节数据(class文件)加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。与那些编译时需要链接的语言不同,java中类型的加载、链接和初始化都在运行期间完成,这种策略虽然在类加载时增加了一些性能开销,但是为java应用程序提供了高度的灵活性,Java能够动态扩展的语言特性就是依赖运行期动态加载动态连接这些特点来实现的。

比如,编写一个面向接口的应用程序,可以等到运行时再指定其实现类。用户可以通过Java预定义或自定义的加载器,让一个本地应用程序在运行时从网络或其它地方加载一个二进制流作为程序代码的一部分。这种组装应用程序的方式已广泛应用于Java程序之中,从最基础的Applet、JSP到相对复杂的OSGI。