三 Runtime Data Area前半(VMS,NMS,NMI,PCcount))

1.概述

image.png

类加载器加载到运行时数据区.png

image.png

线程私有区域和共享区域.png
runtime.png

2.线程

线程的工作空间创建和回收.png

一般后台存在的线程.png

3.程序计数器

  • 介绍


    image.png

    内存.png

    每个线程都有各自私有的pc,存储当前方法jvm指令地址.png

    image.png
  • 例子


    image.png
  • 两道面试题


    image.png

    image.png

    单核.png

    image.png

五 虚拟机栈(java virtual machine stacks)

5.1 概述
  • 指令基于栈而不是寄存器,从而实现跨平台,但性能相对下降
  • 栈:运行时得单位,程序如何执行,
    堆:存储得单位,数据如何存储


    VMS和线程.png

    局部变量只能放:8种基本数据类型和引用地址


    优点.png

    存在OOM但不存在GC
栈中可能出现得异常.png
5.2 栈得存储单位
  • 栈中数据以栈帧得格式存在,每个该线程正在执行得方法各自对应一个栈帧一一对应,是一个内存块,一个数据集,维护方法执行过程
    中各种数据信息。
    原理.png

    示例.png

    不同得线程只是共享堆空间,各自得VMS信息不能共享.png
  • 栈帧得内部结构


    内部得具体结构.png

    线程中的栈帧.png

    下面详细展开这五部分得内容:

5.3 局部变量表
  • 是一个数字数组


    image.png

    线程私有,不存在数据安全问题,随着方法栈帧的销毁,局部变量表也销毁.png
  • Slot:局部变量表的最基本存储单元


    32位数据类型占一个,64位占两个.png

    例子.png
this放在每个局部变量表的PCindex 0 位置.png
过了作用域的局部变量所在的Slot会复用.png

本例子中c占用了b的index2位置slot.png
  • 局部变量和成员变量:


    成员变量和局部变量的区别.png
变量的分类:按照数据类型分:① 基本数据类型  ② 引用数据类型

按照在类中声明的位置分:
① 成员变量:在使用前,都经历过默认初始化赋值

 类变量: linking的prepare阶段:给类变量默认赋值  ---> initial阶段:类变量显式赋值即静态代码块
赋值,实例变量:随着对象的创建,会在堆空间中分配实例变量空间,并进行默认赋值                                
 ② 局部变量:在使用前,必须要进行显式赋值的!否则,编译不通
过
5.4 操作数栈

字节码指令只能操作操作数栈,push,pop保存中间结果,而不是采用索引来访问。

image.png

image.png

5.5 代码追踪
例子.png

可以看到底层的操作数栈堆i、h、m读入时候用的是bytepush和shortpush.png

i++ ++i的区别:

5.6 栈顶缓存技术

都是push和pop对内存中的操作数慢,所以放到cpu寄存器中


栈顶元素缓存在物理cpu寄存器,提高执行效率.png
5.7 动态链接(也可以理解为指向运行时常量区的方法引用)
image.png

image.png
5.8 方法得调用:解析与分派
两种链接方式,是否在编译器可以确定被调用的目标.png

分别对应两种绑定.png
public class AnimalTest {
    public void showAnimal(Animal animal){
        animal.eat();//表现为:晚期绑定
    }
    public void showHunt(Huntable h){
        //Huntable是一个接口
        h.hunt();//表现为:晚期绑定
    }
}
方法对应一个晚期绑定.png

image.png

多态必然衍生出两种绑定

  • 虚方法和非虚方法


    静态编译和早期绑定.png

    子类对象的多态的使用前提是:
    1)类的继承关系
    2)方法的重写
    上面提的前3个其实都不能重写,后面的this super都是确定的


    几个指令.png
 public void show() {
        //invokestatic 子类静态方法
        showStatic("atguigu.com");
        //invokestatic 父类静态方法
        super.showStatic("good!");
        //invokespecial 子类私有方法
        showPrivate("hello!");
        //invokespecial 父类public方法
        super.showCommon();

        //invokevirtual
        showFinal();//因为此方法声明有final,不能被子类重写,所以也认为此方法是非虚方法。
        //虚方法如下:
        //invokevirtual
        showCommon();
        info();

        MethodInterface in = null;
        //invokeinterface
        in.methodA();
    }

这里虽然final是显式是虚方法,但我们不认为他是虚方法,
showCommom方法有没有加super是不同的,加上是非虚,没加是虚

  • invokeDynamic:引入了动态


    lamada表达式.png

    image.png
  • 方法重写的本质和虚方法表的使用
    方法重写的本质:
    1)找到操作数栈顶的第一个元素所执行的对象的实际类型,记作c(this对象);
    2)如果在类型c中找到和常量中描述复合简单名称都相符的方法,则进行访问权限校验,如果通过则返回这个方法的直接应用,查找过程结束。否则返回IllegalAccessError异常
    3)否则,按照继承关系从下往上依次对c的各个父类进行第二部搜索和验证过程
    4)如果始终没有找到合适的方法,抛出AbstractMethodError异常。

  • IllegalAccessError
    程序试图访问过修改一个属性或调用一个方法,这个属性或方法,你没有权限访问,一般会引起编译器错误。

5.9方法得返回地址
5.10一些附加信息
5.11 相关面试题

6 本地方法接口

跳出RDA,进入本地方法接口;

  • 本地方法:


    主要为了融合不同变成语言为java所用.png
比如Object类就标识为native,由C或C++实现
public class Object {

    private static native void registerNatives();
    static {
        registerNatives();
    }

比如Thread中的
private native void start0();//同样native方法

注意native唯独不可以和abstract连用

  • 为什么要用本地方法?
    主要分三个方面举例:


    与外部方法.png

    与os.png
  • 现状:
    该方法使用的越来越少了。

7 本地方法栈NMS

  • 类比VMS,NMS管理本地方法的调用
    image.png

    同样线程私有
    和本地方法接口,本地方法库相关.png

    image.png

你可能感兴趣的:(三 Runtime Data Area前半(VMS,NMS,NMI,PCcount)))