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虚拟机》----虚拟机字节码执行引擎的更多相关文章

  1. 深入理解Java虚拟机(字节码执行引擎)

    深入理解Java虚拟机(字节码执行引擎) 本文首发于微信公众号:BaronTalk 执行引擎是 Java 虚拟机最核心的组成部分之一.「虚拟机」是相对于「物理机」的概念,这两种机器都有代码执行的能力, ...

  2. 深入理解java虚拟机(5)---字节码执行引擎

    字节码是什么东西? 以下是百度的解释: 字节码(Byte-code)是一种包含执行程序.由一序列 op 代码/数据对组成的二进制文件.字节码是一种中间码,它比机器码更抽象. 它经常被看作是包含一个执行 ...

  3. 【java虚拟机系列】从java虚拟机字节码执行引擎的执行过程来彻底理解java的多态性

    我们知道面向对象语言的三大特点之一就是多态性,而java作为一种面向对象的语言,自然也满足多态性,我们也知道java中的多态包括重载与重写,我们也知道在C++中动态多态是通过虚函数来实现的,而虚函数是 ...

  4. 《深入理解Java虚拟机》-----第8章 虚拟机字节码执行引擎——Java高级开发必须懂的

    概述 执行引擎是Java虚拟机最核心的组成部分之一.“虚拟机”是一个相对于“物理机”的概念 ,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的,而 ...

  5. 深入理解Java虚拟机读书笔记5----虚拟机字节码执行引擎

    五 虚拟机字节码执行引擎   1 运行时栈帧结构     ---栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,是虚拟机运行时数据区中的虚拟机栈的栈元素.     ---栈帧中存储了方法的局部变 ...

  6. 深入理解Java虚拟机(类文件结构+类加载机制+字节码执行引擎)

    目录 1.类文件结构 1.1 Class类文件结构 1.2 魔数与Class文件的版本 1.3 常量池 1.4 访问标志 1.5 类索引.父索引与接口索引集合 1.6 字段表集合 1.7 方法集合 1 ...

  7. Java虚拟机--虚拟机字节码执行引擎

    Java虚拟机--虚拟机字节码执行引擎 所有的Java虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果. 运行时栈帧结构 用于支持虚拟机进行方法调用和方 ...

  8. java虚拟机字节码执行引擎

    定义 java虚拟机字节码执行引擎是jvm最核心的组成部分之一,它做的事情很简单:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.在不同的虚拟机实现里,执行引擎在执行java代码 ...

  9. Java虚拟机-字节码执行引擎

    概述 Java虚拟机规范中制定了虚拟机字节码执行引擎的概念模型,成为各种虚拟机执行引擎的统一外观(Facade).不同的虚拟机引擎会包含两种执行模式,解释执行和编译执行. 运行时帧栈结构 栈帧(Sta ...

  10. JAVA虚拟机:虚拟机字节码执行引擎

    “虚拟机”是一个相对“物理机”的概念,这两种机器都有代码执行能力. 物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的. 虚拟机的执行引擎由自己实现,自行制定指令集与执行引擎的结构体系 ...

随机推荐

  1. [Java多线程]-ThreadLocal源码及原理的深入分析

    ThreadLocal<T>类:以空间换时间提供一种多线程更快捷访问变量的方式.这种方式不存在竞争,所以也不存在并发的安全性问题. //-------------------------- ...

  2. [DeeplearningAI笔记]卷积神经网络3.6-3.9交并比/非极大值抑制/Anchor boxes/YOLO算法

    4.3目标检测 觉得有用的话,欢迎一起讨论相互学习~Follow Me 3.6交并比intersection over union 交并比函数(loU)可以用来评价对象检测算法,可以被用来进一步改善对 ...

  3. 子序列 sub sequence问题,例:最长公共子序列,[LeetCode] Distinct Subsequences(求子序列个数)

    引言 子序列和子字符串或者连续子集的不同之处在于,子序列不需要是原序列上连续的值. 对于子序列的题目,大多数需要用到DP的思想,因此,状态转移是关键. 这里摘录两个常见子序列问题及其解法. 例题1, ...

  4. 解决VS Code编译调试中文输出乱码

    最近尝试用VS Code配置了C和C++的编译调试环境,结果遇到了中文输出乱码问题,查阅网上竟然还没有相关问题,有怀疑是mingw中文支持问题,但最后证明是VS Code编码问题. 解决方案: 文件- ...

  5. Integer Numbers

    ZOJ Problem Set - 3365 Integer Numbers Time Limit: 1 Second      Memory Limit: 32768 KB      Special ...

  6. 【洛谷 P4437】 [HNOI/AHOI2018]排列(贪心,堆)

    题目链接 如果\(j<=k,a_{p[j]}!=p[k]\)可以理解为如果\(a_{p[j]}=p[k]\),那么\(k\)一定要放在\(j\)前面,也就是\(a_j\)在\(j\)前面. 于是 ...

  7. 常见的bug

    常见bug 一. Android系统功能测试设计的测试用例: a.对所测APP划分模块 b.详细列出每个模块的功能点(使用Xmind绘制功能图) c.使用等价类划分.边界值.场景法等对各功能点编写测试 ...

  8. C++学习之路(九):从菱形继承引入的对象模型

    一.单继承 class A {int a;}; class B : public A {int b;}; 普通的单继承关系,类的大小是由其虚表指针和非静态成员函数大小决定.故上述sizeof(A)的大 ...

  9. 【并行计算】基于OpenMP的并行编程

    我们目前的计算机都是基于冯偌伊曼结构的,在MIMD作为主要研究对象的系统中,分为两种类型:共享内存系统和分布式内存系统,之前我们介绍的基于MPI方式的并行计算编程是属于分布式内存系统的方式,现在我们研 ...

  10. 2017 NEERC

    2017 NEERC Problem A. Archery Tournament 题目描述:在二维平面上,会陆续出现一些圆,以及一些询问,询问点是否在圆内,如果是,则输出那个圆,并把那个圆删掉,否则输 ...