
我所有的文章都与Github– Java-Notes同步更新. 我想了解JVM,HashMap源代码分析,spring相关的,剑指提供的解决方案(Java版),可以单击星号. 您可以看到我的github主页,该页面每天更新.
堆栈框架是虚拟机堆栈的一个单元. 前面已经解释了运行时数据区和类加载过程. 现在,让我们看一下虚拟机中的堆栈框架. 这应该被视为运行时数据区域,如果您不了解,可以参考我的博客文章JVM内存结构
以下内容在运行时存储在堆栈框架中
局部变量表是一组变量值存储空间,用于存储方法参数和方法中定义的局部变量.
在编译过程中将大小写入字节码,并在Code属性中将max_local属性(即以下本地变量)写入
局部变量表的容量是以变量插槽(变量插槽)为最小单位的. 虚拟机并未明确指出插槽应占用的内存空间大小,但很明确的指示每个插槽应能够存储以下8种类型之一. (如果它是64位数据类型,例如long或double,则需要两个插槽)
不应该说前六个,它是基本数据类型,引用是什么
引用是对对象实例的引用
功能:
为字节码指令jsr,jsr_w和ret提供,它们指向字节码指令的地址

很少见.
局部变量表中的局部变量与之前加载类时的类变量(静态修改)不同. 没有所谓的“准备阶段”,因此没有设置初始值的阶段. 如果您不知道,可以参考我的文章以加载此文章. 阅读准备阶段后,您应该知道. 类加载过程
因此,当我们这样编写程序时,您将知道是否进行比较
其他类型的零值
为了尽可能节省堆栈空间,可以重用局部变量表的Slot. 方法主体中定义的变量的范围不一定覆盖整个方法主体. 如果当前字节码PC计数器的值已超出某个变量的范围栈帧,则可以将此变量对应的插槽分配给其他变量.
但是,这种方法会有一些缺点,让我们来看下面的代码示例
公共类Test2 {
public static void main(字符串[] args){
byte []占位符=新字节[64 * 1024 * 1024];
System.gc();

}
}
复制代码
我们通过配置虚拟机参数-verbose: gc来打印垃圾回收的结果
我们看到他没有回收.
让我们修改代码
public class Test2 {
public static void main(String[] args) {
{
byte[] placeholder = new byte[64 * 1024 * 1024];
}
System.gc();
}
}
复制代码
他仍然没有回收. 有理由认为placeHolder的范围仅在花括号中. 执行gc方法后,他将不再使用它. 它已经是死物了. 为什么?不回收吗?
我们将再次对其进行修改
公共类Test2 {

public static void main(字符串[] args){
{
byte []占位符=新字节[64 * 1024 * 1024];
}
int a = 0;
System.gc();
}
}
复制代码
我们看到这次垃圾收集器正在工作,为什么?
占位符可以回收的根本原因是在局部变量表的Slot中是否有对占位符数组对象的引用.

在第一个修改中,尽管代码离开了变量的范围,但是在那之后,没有对本地变量表的读或写操作,并且最初由变量占用的Slot未被任何人重用. 其他变量. 因此,作为GC根目录一部分的局部变量表仍保持其关联性(如果您不知道可以用作GC根目录的内容,可以参考我的文章JVM垃圾收集)
第二次,它改变了上面的情况
因此,当您遇到一个方法时,其背后的代码将执行一些非常耗时的操作,并且前部定义了占用大量内存且实际上并未使用的变量. 您应该手动将其设置为null.
许多工具类都有此操作,例如ArrayList和Stack中的remove方法,您还可以在其他工具类中找到该方法,以查看是否存在这种操作
操作数栈在执行方法期间记录字节码指令,然后将其压入并弹出操作数栈
大小也已在编译时确定. 字节码文件的Code属性中的max_stacks数据项,即下图中的堆栈
仅在执行方法时栈帧,操作数堆栈为空. 在该方法执行期间,各种字节码指令将被推入和移出操作数堆栈.
每个堆栈帧都包含对运行时常量池中堆栈帧所属方法的引用. 保留此参考以支持方法调用期间的动态连接
如果查看字节码文件的组成和类加载过程,应该知道字节码文件中有许多符号引用.
其中一些符号引用将在类装入解析阶段或首次使用它们时转换为直接引用. 这种转换称为静态分辨率
另一部分将在运行期间转换为直接引用,这部分称为动态链接
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-164562-1.html
面对伊拉克要倒向请求帮助空袭