3. 动态链接
- Dynnamic Lining
- 每个栈帧内部包含: 指向 运行时常量池中,该栈帧 所属方法的引用
- 就是为了支持当前方法的代码能够实现: 动态链接
Java源文件被编译成class字节码后,
1. 所有的变量和方法引用,都作为符号引用(Symbolic Reference)保存在class文件的常量池
2. 描述一个方法调用了另外的其他方法,就是通过常量池中指向方法的符号引用来表示
动态链接的作用,就是为了将这些符号引用,转换为调用方法的直接引用
3. 通过一个方法来分析
3.1 invokevirtual: 去激活另外一个自定义方法,或者系统的方法
3.2 每个string都会被初始到 方法区的 常量池中
3.3: 方法的引用,属性的引用(保存在常量池)
3.4:常量池保存的符号引用也会嵌套
多线程共享,多对象共享,节省内存
不用这个行不行: 行!
1. 在栈帧中直接保存对象的引用地址来获取堆中的对象
2. 每个线程的每个方法都要保存地址引用
其实就是添加了一个方法区的常量池缓冲层
对象共享,线程共享,节省内存
4. 方法返回值
1. 存放调用用该方法的pc寄存器的值
1.1 并非返回的具体的值, 具体的返回值放到操作数栈里面去了
1.2 以便方法结束后,能知道下一个指令去哪里执行
1.3 将pc寄存器里面的值,交给执行引擎,让他去执行后续的操作,即继续执行调用该方法的方法
2. 方法结束: 方法退出后,都返回到该方法被调用的位置
2.1 正常执行完成
- 调用者的pc寄存器的值作为返回值,即调用该方法的指令的下一条指令的地址
2.2 出现没有处理的异常,非正常退出
- 返回地址要通过异常表来确定,栈帧中一般不会保存这部分信息
3. 方法正常调用完后,具体需要哪一个返回指令
3.1 根据方法返回值的实际数据类型而定:
3.2 ireturn:boolean,byte,char,short,int
3.3 lreturn: long
3.4 freturn: float
3.5 dreturn: double
3.6 areurn: 引用数据类型
3.7 return: void, 构造器 , 类的构造器
5、栈面试题目
1. 举例栈溢出的情况?(StackOverFlowError)
不恰当的方法递归调用
jvm的栈的大小默认是固定的,因此如果多个不当的递归调用,就会引发栈溢出
jvm的栈的大小如果是动态的,多个不点那个递归, 就会引发OutOfMemory
2. 调整栈大小,就能保证不出现溢出吗?
不能,不恰当的递归,最终依然会导致溢出,不过只是时间先后的问题
3. 分配的栈内存越大越好吗?
机器牛逼的话,同比放大的情况下,越大越好,
不然的话,栈内存过大,其他内存就小了
4. 垃圾回收是否会涉及到虚拟机栈
不会,栈帧内存随着方法的弹栈就会被销毁,随着线程的结束会销毁该栈
5. 方法中定义的局部变量是否是线程安全的
5.1 基本数据类型是安全的
5.2 引用类型数据可能会发生逃逸