《java虚拟机》----虚拟机字节码执行引擎
No1:
物理机的执行引擎是直接建立在处理器、硬件、指令集合操作系统层面上的,而虚拟机的执行引擎则是由自己实现的,因此可以自行制定指令集与执行引擎的结构体系,并且能够执行那些不被硬件直接支持的指令集格式。
No2:
执行引擎在执行java代码的时候可能会有解释执行(通过解释器执行)和编译执行(通过即时编译器产生本地代码执行)两种选择。
No3:
栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构,它时虚拟机运行时数据区中的虚拟机栈的栈元素。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。每一个方法从调用开始至执行完成的过程,都对应着一个栈帧在虚拟机里面从入栈到出栈的过程。
No4:
对于执行引擎来说,在活动线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧,与这个栈帧相关联的方法称为当前方法。
No5:
局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。
局部变量表的容量以变量槽(Slot)为最大单位,每个Slot都应该能存放一个boolean、byte、char、short、int、float、reference或returnAddress类型的数据。
reference类型表示对一个对象实例的引用,虚拟机能通过这个引用做到两点
1.从此引用中直接或间接地查找到对象在java堆中的数据存放的起始地址索引
2.此引用中直接或间接地查找到对象所属数据类型在方法区中的存储的类型信息
No6:
局部变量表建立在线程的堆栈上,是线程私有的数据,无论读写两个连续的Slot是否为原子操作,都不会引起数据安全问题。
No7:
虚拟机通过索引定位的方式使用局部变量表,索引值范围从0开始至局部变量表最大的Slot数量。
No8:
对象原本所占用的Slot还没有被其他变量所复用,所以GC Root一部分的局部变量表仍然保持着对它的关联。如果手动将其设置为null值(把变量对应的局部变量表Slot清空)System.gc()才会回收掉内存。
No9:
类变量有两次赋初始值的过程,一次在准备阶段,赋予系统初始值;另外一次在初始化阶段,赋予程序员定义的初始值。
局部变量如果定义了但没有赋初始值是不能使用的。
No10:
整数加法的字节码指令iadd在运行的时候操作数栈中最接近栈顶的两个元素已经存入了两个int型的数值,当执行这个指令时,会将这两个int值出栈并相加,然后将相加的结果入栈。
No11:
操作栈是一个后进先出栈。
No12:
每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接(Dynamic Linking)。Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用作为参数。这些符号引用一部分会在类加载器阶段或者第一次使用的时候就转化为直接引用,这种转化称为静态解析。另外一部分将在每一次运行期间转化为直接引用,这部分称为动态连接。
No13:
所有方法调用中的目标方法在Class文件里面都是一个常量池中的符号引用,在类加载的解析阶段,会将其中的一部分符号引用转化为直接引用,这种解析能成立的前提是:方法在程序真正运行之前就有一个可确定的调用版本,并且这个方法的调用版本在运行期是不可改变的。
调用目标在程序代码写好、编译器进行编译时就必须确定下来,这类方法的调用称为解析;
No14:
在java语言中符合“编译器可知,运行期不可变”这个要求的方法,主要包括静态方法和私有方法两大类。
No15:
分派调用将揭示多态特征的一些最基本的体现。
No16:
分派----静态分派:
public class StaticDispatch{
static abstract class Human{} static class Man extends Human{} static class Woman extends Human{} public void sayHello(Human guy) {
System.out.println("hello,guy");
} public void sayHello(Man guy) {
System.out.println("hello,gentleman");
} public void sayHello(Woamn guy) {
System.out.println("hello,lady");
} public static void main(String[] args){
Human man = new Man();
Human woman = new Woman();
StaticDispatch sr = new StaicDispatch();
sr.sayHello(man);
sr.sayHello(woman);
}
}
运行结果
hello.guy
hello.guy
Human man = new Man();
Human为变量的静态类型,Man为变量的实际类型;
静态类型和实际类型的区别:
1.静态类型的变化仅仅在使用时发生,变量本身的静态类型不会被改变,并且最终的静态类型是在编译期可知的
2.实际类型变化的结果在运行期才可确定,编译器在编译程序的时候并不知道一个对象的实际类型是什么
虚拟机(编译器)在重载时是通过参数的静态类型而不是实际类型作为判定依据的。静态类型是编译期可知的,在编译阶段,javac编译器会根据参数的静态类型决定哪个重载版本。
所有依赖静态类型来定位方法执行版本的分派动作称为静态分派。静态分派的典型应用是方法重载,静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的。
public class Overload {
public static void sayHello(char arg) {
System.out.println("hello char");
} public static void sayHello(int arg) {
System.out.println("hello int");
} public static void sayHello(long arg) {
System.out.println("hello long");
} public static void sayHello(Character arg) {
System.out.println("hello Character");
} public static void sayHello(Serializable arg) {
System.out.println("hello Serializable");
} public static void sayHello(Object arg) {
System.out.println("hello Object");
} public static void sayHello(char... arg) {
System.out.println("hello char...");
} public static void main(String[] args) {
sayHello('a');
}
}
优先级顺序char->int->long->Character->Serializable->Object->char...
No17:
动态分派和重写有密切的关联。重载是静态的,重写是动态的。
No18:
方法的接受者与方法的参数统称为方法的宗量,单分派是根据一个宗量对目标方法进行选择,多分派是根据多余一个宗量对目标方法进行选择。
public class Dispatch{
static class QQ{}
static class _360{} public static class Father{
public void hardChoice(QQ arg){
System.out.println("father choose qq");
} public void hardChoice(_360 arg){
System.out.println("father choose 360");
}
} public static class Son extends Father{
public void hardChoice(QQ arg){
System.out.println("son choose qq");
} public void hardChoice(_360 arg){
System.out.println("son choose 360");
}
} public static void main(String[] args){
Father father = new Father();
Father son = new Son();
father.hardChoice(new _360());
son.hardChoice(new QQ());
}
}
运行结果
father choose 360
son choose qq
静态分派:1.静态类型是Father还是Son 2.方法参数是QQ还是360 所以是多分派类型
动态分派:1.此方法接受者实际类型是Father还是Son
No19:
总结:java语言是一门静态多分派、动态单分派的语言。
No20:
动态类型语言的关键特征是它的类型检查的主体过程是在运行期而不是编译器。
NegativeArraySizeException是运行时异常,NoClassDefFoundError是连接时异常。
No21:
静态类型语言在编译期确定类型,最显著的好处是编译器可以提供严谨的类型检查,这样与类型相关的问题能在编码的时候就及时发现,利于稳定性及代码达到更大规模。
动态类型语言在运行期确定类型,可以为开发人员提供更大的灵活性,某些在静态类型语言中需要大量“臃肿”代码来实现的功能,由动态类型语言来实现可能会更加清晰和简洁,清晰和简洁通常也就意味着开发效率的提升。
《java虚拟机》----虚拟机字节码执行引擎的更多相关文章
- 深入理解Java虚拟机(字节码执行引擎)
深入理解Java虚拟机(字节码执行引擎) 本文首发于微信公众号:BaronTalk 执行引擎是 Java 虚拟机最核心的组成部分之一.「虚拟机」是相对于「物理机」的概念,这两种机器都有代码执行的能力, ...
- 深入理解java虚拟机(5)---字节码执行引擎
字节码是什么东西? 以下是百度的解释: 字节码(Byte-code)是一种包含执行程序.由一序列 op 代码/数据对组成的二进制文件.字节码是一种中间码,它比机器码更抽象. 它经常被看作是包含一个执行 ...
- 【java虚拟机系列】从java虚拟机字节码执行引擎的执行过程来彻底理解java的多态性
我们知道面向对象语言的三大特点之一就是多态性,而java作为一种面向对象的语言,自然也满足多态性,我们也知道java中的多态包括重载与重写,我们也知道在C++中动态多态是通过虚函数来实现的,而虚函数是 ...
- 《深入理解Java虚拟机》-----第8章 虚拟机字节码执行引擎——Java高级开发必须懂的
概述 执行引擎是Java虚拟机最核心的组成部分之一.“虚拟机”是一个相对于“物理机”的概念 ,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的,而 ...
- 深入理解Java虚拟机读书笔记5----虚拟机字节码执行引擎
五 虚拟机字节码执行引擎 1 运行时栈帧结构 ---栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,是虚拟机运行时数据区中的虚拟机栈的栈元素. ---栈帧中存储了方法的局部变 ...
- 深入理解Java虚拟机(类文件结构+类加载机制+字节码执行引擎)
目录 1.类文件结构 1.1 Class类文件结构 1.2 魔数与Class文件的版本 1.3 常量池 1.4 访问标志 1.5 类索引.父索引与接口索引集合 1.6 字段表集合 1.7 方法集合 1 ...
- Java虚拟机--虚拟机字节码执行引擎
Java虚拟机--虚拟机字节码执行引擎 所有的Java虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果. 运行时栈帧结构 用于支持虚拟机进行方法调用和方 ...
- java虚拟机字节码执行引擎
定义 java虚拟机字节码执行引擎是jvm最核心的组成部分之一,它做的事情很简单:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.在不同的虚拟机实现里,执行引擎在执行java代码 ...
- Java虚拟机-字节码执行引擎
概述 Java虚拟机规范中制定了虚拟机字节码执行引擎的概念模型,成为各种虚拟机执行引擎的统一外观(Facade).不同的虚拟机引擎会包含两种执行模式,解释执行和编译执行. 运行时帧栈结构 栈帧(Sta ...
- JAVA虚拟机:虚拟机字节码执行引擎
“虚拟机”是一个相对“物理机”的概念,这两种机器都有代码执行能力. 物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的. 虚拟机的执行引擎由自己实现,自行制定指令集与执行引擎的结构体系 ...
随机推荐
- McNemar test麦克尼马尔检验
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录视频) https://study.163.com/course/introduction.htm?courseId=1005269003&u ...
- PlantUML类图
PlantUML类图 雨客 2016-04-08 11:38:03 浏览796 评论0 摘要: 类之间的关系 PlantUML用下面的符号来表示类之间的关系: 泛化,Generalization: ...
- struts标签错误:Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core"
今天使用eclipse开发ssh,出现Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/co ...
- 前端PHP入门-033-连接数据库-天龙八步
php检查MySQL的支持是否开启? 若没有看到mysqli扩展在windows服务器下,打开php.ini文件,将php_mysqli.dll打开即可! 注意: 从PHP7开始默认不再支持mysql ...
- zTree使用技巧与详解
zTree--Jquery 树插件,是在后台管理页面中常使用到的插件. 使用效果图: 核心代码: zTree配置: var setting = { data:{simpleData:{enable:t ...
- 维护后面的position sg函数概念,离线+线段 bzoj 3339
3339: Rmq Problem Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1160 Solved: 596[Submit][Status][ ...
- 软件测试(三)—— 参数化测试用例(Nextday.java)
import static org.junit.Assert.*; import java.lang.reflect.Array; import java.util.Arrays; import ja ...
- 前端开发必知必会:CSS Position 全解析
此文根据Steven Bradley的<How Well Do You Understand CSS Positioning?>所译,整个译文带有我自己的理解与思想,如果译得不好或不对之处 ...
- 每天一条linux命令(1):ls命令
ls命令是linux下最常用的命令.ls命令就是list的缩写缺省下ls用来打印出当前目录的清单如果ls指定其他目录那么就会显示指定目录里的文件及文件夹清单. 通过ls 命令不仅可以查看linu ...
- Python设计模式中单例模式的实现及在Tornado中的应用
单例模式的实现方式 将类实例绑定到类变量上 class Singleton(object): _instance = None def new(cls, *args): if not isinstan ...