《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虚拟机:虚拟机字节码执行引擎
		
“虚拟机”是一个相对“物理机”的概念,这两种机器都有代码执行能力. 物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的. 虚拟机的执行引擎由自己实现,自行制定指令集与执行引擎的结构体系 ...
 
随机推荐
- MySQL语句查看各个数据库占用空间
			
select table_schema, sum(DATA_LENGTH)+sum(INDEX_LENGTH) from information_schema.tables group by tabl ...
 - Bootstrap3和Bootsrap4的区别
			
Bootstrap3和Bootstap4的区别 1.Bootsrap4 css文件减少了40%以上 2.Bootsrap4已经不支持IE8以及IOS 6的支持 3.多了些类好组件
 - HDU 1930 CRT
			
也是很模板的一道题,给出一些数,分割,模数固定是4个互质的. /** @Date : 2017-09-16 23:54:51 * @FileName: HDU 1930 CRT.cpp * @Plat ...
 - SPOJ DQUERY 离线树状数组+离散化
			
LINK 题意:给出$(n <= 30000)$个数,$q <= 2e5$个查询,每个查询要求给出$[l,r]$内不同元素的个数 思路:这题可用主席树查询历史版本的方法做,感觉这个比较容易 ...
 - Android Studio 更新失败的解决办法
			
编辑$ANDROID_STUDIO_HOME/bin/ 下的 studio.exe.vmoptions(如果系统用的Ubuntu,文件应该是studio.vmoptions或者如果是64位系统,应该是 ...
 - ADO.NET中带参数的Sql语句的陷阱
			
1.使用Parameter //利用构造函数方式 ,不推荐这样写 Parameter p =new Parameter("@id",值); cmd.Parameters.Add(p ...
 - NSPredicate--谓词(is)
			
技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http://weibo.com/luohanchenyilong NSPredicate 技术博客http:// ...
 - 【Git】git clone与git pull区别
			
从字面意思也可以理解,都是往下拉代码,git clone是克隆,git pull 是拉.但是,也有区别: 从远程服务器克隆一个一模一样的版本库到本地,复制的是整个版本库,叫做clone.(clone是 ...
 - ARP投毒攻击
			
原理:通过分别伪装成客户机和服务器IP,将自己的MAC地址绑定在IP上,ARP错误的将IP解析为中间人MAC地址,从而来欺骗服务器网关和客户机,使信息必须通过客户机.
 - 152.Maximum Product Subarray---dp---连续子数组的最大乘积---《编程之美》2.13子数组的最大乘积
			
题目链接:https://leetcode.com/problems/maximum-product-subarray/description/ 题目大意:给出一串数组,找出连续子数组中乘积最大的子数 ...