JVM 虚拟机栈

JVM 虚拟机栈描述

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.2

2.5.2. Java Virtual Machine Stacks

Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. A Java Virtual Machine stack stores frames (§2.6). A Java Virtual Machine stack is analogous to the stack of a conventional language such as C: it holds local variables and partial results, and plays a part in method invocation and return. Because the Java Virtual Machine stack is never manipulated directly except to push and pop frames, frames may be heap allocated. The memory for a Java Virtual Machine stack does not need to be contiguous.

In the First Edition of The Java® Virtual Machine Specification, the Java Virtual Machine stack was known as the Java stack.

This specification permits Java Virtual Machine stacks either to be of a fixed size or to dynamically expand and contract as required by the computation. If the Java Virtual Machine stacks are of a fixed size, the size of each Java Virtual Machine stack may be chosen independently when that stack is created.

A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of Java Virtual Machine stacks, as well as, in the case of dynamically expanding or contracting Java Virtual Machine stacks, control over the maximum and minimum sizes.

The following exceptional conditions are associated with Java Virtual Machine stacks:

  • If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a StackOverflowError.

  • If Java Virtual Machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java Virtual Machine stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

 

栈是运行时的单位;堆是存储的单位

Java虚拟机栈的作用

主管Java程序的进行,它保存方法的局部变量,部分结果,并参与方法的调用和返回

每个线程都会创建一个虚拟机栈  是线程私有的  和PC寄存器一样都是线程私有的

栈的特点:

1.展示一种快速有效的分配存储方式  访问速度仅次于程序计数器

2.JVM直接对Java栈的操作只有两个

  > 每个方法 伴随这进栈(入栈/压栈)

 > 执行结束后的出栈工作

对于栈来说 不存在垃圾回收问题,但是存在OOM

PC寄存器 也不存在垃圾回收问题和OOM


JVM参数参考文档

https://docs.oracle.com/en/java/javase/11/tools/java.html#GUID-3B1CE181-CD30-4178-9602-230B800D4FAE

https://docs.oracle.com/en/java/javase/11/tools/java.html#GUID-3B1CE181-CD30-4178-9602-230B800D4FAE


线程都有自己的栈,栈中的数据都是以 栈帧(Stack Frame)的格式存在的

在这个线程正在执行的每个方法都各自对应一个栈帧(Stack Frame)

栈帧是一个内存区块,是一个数据集,维系着方法执行过程中的各种数据信息

反编译命令  javap -v  XXX.class

 

阿里的JDK   GCIH

http://itindex.net/detail/49388-java-%E5%86%85%E5%AD%98-jvm


 



局部变量表字节码

(

行号14(源码的14行)对应的起始PC 8(字节码的行数)

长度是作用域的范围:因为字节码的长度是16   所有 起始PC+长度都是=16 


/**
     * 如果当前帧是由构造方法或者实例方法(非静态方法)创建的
     * 那么该对象引用this将会存放在index为0的slot处
     * 其余的参数按照参数的顺序继续排列
     */
    public static void testStatic(){
        LocalVariablesTest test = new LocalVariablesTest();
        Date date = new Date();
        int count = 10;
        System.out.println(count);
        //为什么静态方法不能使用this,因为this变量不存在于当前方法的局部变量表中!!
//        System.out.println(this.count);
    }

 /*
    变量的分类:按照数据类型分:① 基本数据类型  ② 引用数据类型
                按照在类中声明的位置分:① 成员变量:在使用前,都经历过默认初始化赋值
                                                类变量: linking的prepare阶段:给类变量默认赋值  ---> initial阶段:给类变量显式赋值即静态代码块赋值
                                                实例变量:随着对象的创建,会在堆空间中分配实例变量空间,并进行默认赋值
                                       ② 局部变量:在使用前,必须要进行显式赋值的!否则,编译不通过
     */
    public void test5Temp(){
        int num;
        //System.out.println(num);//错误信息:变量num未进行初始化
    }



 


 

 


案例

package com.atguigu.java2;

/**
 * 说明早期绑定和晚期绑定的例子
 * @author shkstart
 * @create 2020 上午 11:59
 */
class Animal{

    public void eat(){
        System.out.println("动物进食");
    }
}
interface Huntable{
    void hunt();
}
class Dog extends Animal implements Huntable{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    @Override
    public void hunt() {
        System.out.println("捕食耗子,多管闲事");
    }
}

class Cat extends Animal implements Huntable{

    public Cat(){
        super();//表现为:早期绑定
    }

    public Cat(String name){
        this();//表现为:早期绑定
    }

    @Override
    public void eat() {
        super.eat();//表现为:早期绑定
        System.out.println("猫吃鱼");
    }

    @Override
    public void hunt() {
        System.out.println("捕食耗子,天经地义");
    }
}
public class AnimalTest {
    public void showAnimal(Animal animal){
        animal.eat();//表现为:晚期绑定
    }
    public void showHunt(Huntable h){
        h.hunt();//表现为:晚期绑定
    }
}

package com.atguigu.java2;

/**
 * 解析调用中非虚方法、虚方法的测试
 *
 * invokestatic指令和invokespecial指令调用的方法称为非虚方法
 * @author shkstart
 * @create 2020 下午 12:07
 */
class Father {
    public Father() {
        System.out.println("father的构造器");
    }

    public static void showStatic(String str) {
        System.out.println("father " + str);
    }

    public final void showFinal() {
        System.out.println("father show final");
    }

    public void showCommon() {
        System.out.println("father 普通方法");
    }
}

public class Son extends Father {
    public Son() {
        //invokespecial
        super();
    }
    public Son(int age) {
        //invokespecial
        this();
    }
    //不是重写的父类的静态方法,因为静态方法不能被重写!
    public static void showStatic(String str) {
        System.out.println("son " + str);
    }
    private void showPrivate(String str) {
        System.out.println("son private" + str);
    }

    public void show() {
        //invokestatic
        showStatic("atguigu.com");
        //invokestatic
        super.showStatic("good!");
        //invokespecial
        showPrivate("hello!");
        //invokespecial
        super.showCommon();

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

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

    public void info(){

    }

    public void display(Father f){
        f.showCommon();
    }

    public static void main(String[] args) {
        Son so = new Son();
        so.show();
    }
}

interface MethodInterface{
    void methodA();
}

 




PC寄存器保存的是下一条要执行指令的值

 

/**
 *
 * 返回指令包含ireturn(当返回值是boolean、byte、char、short和int类型时使用)、
 * lreturn、freturn、dreturn以及areturn,另外还有一个return指令供声明为void的方法、
 * 实例初始化方法、类和接口的初始化方法使用。
 **/

栈的面试题

1.举例栈溢出的情况

  StackOverFlowError

  -Xss 设置栈的大小 溢出OOM

2.调整栈大小,就能保证不出现溢出么?

 不能 智能延迟溢出时间

程序计数器    不会error 不会GC

本地方法栈    会error 不会GC

虚拟机栈      会error  不会GC

堆                会error  会GC

方法去          会error  会GC

3.分配的栈内存越大越好么?

不是的 ,内存空间有限的 栈内存大了 栈的数量可能就会边少

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值