您的位置:首页 > 汽车 > 时评 > 制作网页的过程中可以单击什么标签显示网页效果_自动优化app_东莞全网营销推广_友情链接模板

制作网页的过程中可以单击什么标签显示网页效果_自动优化app_东莞全网营销推广_友情链接模板

2025/4/28 3:14:00 来源:https://blog.csdn.net/weixin_74019079/article/details/147271787  浏览:    关键词:制作网页的过程中可以单击什么标签显示网页效果_自动优化app_东莞全网营销推广_友情链接模板
制作网页的过程中可以单击什么标签显示网页效果_自动优化app_东莞全网营销推广_友情链接模板

一、程序计数器

(1)程序计数器介绍

  1. 作用:当线程执行 Java 方法时,程序计数器记录该线程下一条要执行的字节码指令的地址;当线程执行本地方法时,程序计数器的值为未指定(undefined)
  2. 特点:由于只需记录指令地址,程序计数器占用空间小,不会出现内存溢出问题。它是线程私有的,独立于线程栈,生命周期与线程一致
  3. 功能:当发生线程切换,或者程序遇到分支、循环、跳转、异常处理等情况时,依靠程序计数器来确定接下来从哪里继续执行

(2)举例说明

当一个线程运行到某个方法时,会从方法区的类信息里找到该方法对应的字节码文件,字节码文件由一系列指令构成。方法开始运行,若不是热点代码,每行指令会由字节码解释器逐行解释执行。在执行过程中,程序计数器会记录当前线程下一条要执行的字节码指令在字节码文件中的偏移地址

(3)两个常见问题

  1. 存储指令地址的作用发生线程切换、程序有分支等情况时,程序计数器能确定后续要运行的指令,保证程序连贯执行
  2. 线程私有的原因多线程环境下,CPU 核在不同线程间切换,同一时刻一核执行一线程,若多线程共用会产生覆盖问题

二、虚拟机栈

  1. 每个线程都有一个专属的虚拟机栈,它是线程私有的,其生命周期和线程一致,与程序计数器相同。它以栈帧为基本单位,主要操作是栈帧的入栈和出栈,不存在垃圾回收问题。若线程栈数量过多,会导致内存溢出(OutOfMemoryError);若一个线程栈内方法调用层数过多,会导致栈溢出(StackOverflowError)
  2. 栈帧是虚拟机栈的基本单位,遵循先进后出的原则,同一时刻只有栈顶的栈帧对应的方法在运行。方法开始执行时,对应的栈帧入栈;方法执行完毕,栈帧出栈。栈帧包含局部变量表、操作数栈、动态链接、方法返回地址以及一些附加信息
  3. 局部变量表用于存储方法的形参以及方法内部定义的局部变量。在方法调用时,实参的值会传递给形参变量。局部变量表的大小在编译阶段就已确定,32 位的数据类型(如 int、float 等)占用一个 slot,64 位的数据类型(如 long、double )占用两个连续的 slot。对于基本数据类型,slot 中存储的是具体的值;对于引用数据类型,slot 中存储的是对象的引用地址
  4. 操作数栈用于存放计算过程中的中间结果,它会根据字节码指令从局部变量表或者其他地方提取数据进行运算。操作数栈的深度在编译时也已经确定
  5. 动态链接的作用是将运行时常量池中的符号引用转换为直接引用。在类加载过程中,方法的调用以符号引用的形式存在于常量池中。在运行时,动态链接会根据这些符号引用找到对应的方法的实际内存地址。对于虚方法调用,还需要在运行时根据对象的实际类型来确定具体调用的方法版本,而不是简单地根据对象地址找类型再确定方法
  6. 方法返回地址记录的是调用该方法的位置,也就是调用该方法的指令的下一条指令的地址。当当前方法执行结束,对应的栈帧出栈,程序会根据这个返回地址继续执行上层方法中后续的指令
  7. 非虚方法在编译阶段就可以确定要调用的具体方法,像静态方法、私有方法、final 方法都属于非虚方法,因为它们的调用目标在编译时就已明确,不会因为对象的实际类型不同而改变。而虚方法由于多态机制的存在,在编译时无法确定具体调用的是哪个类的方法版本

三、本地方法栈

  1. 本地方法栈和虚拟机栈类似,主要区别在于虚拟机栈为执行 Java 方法服务,而本地方法栈为执行本地方法(通常用 C、C++ 编写)服务,栈中的栈帧由调用本地方法形成
  2. 随着 JVM 发展,部分 JVM 实现将本地方法栈和虚拟机栈进行了合并,即它们共用一个栈。这个栈里可能包含 Java 方法的栈帧,也可能包含本地方法(如 C、C++ 方法)的栈帧

四、其它相关知识

在 JVM 中一个多态方法的调用过程如下:

  1. 线程的某个方法里使用多态机制创建对象,即父类变量指向子类对象。若子类对象所属类的信息尚未加载进 JVM,会触发类的加载。类加载器会将该类的二进制字节码文件加载进 JVM,若其父类也未加载,则先加载父类,再加载子类
  2. 接着,根据字节码文件,将类的定义(包括类中属性、方法定义及方法字节码)、类的继承关系等信息存于方法区的类信息部分;把类中的数字、常量、类名、属性名、方法名(符号引用)等放入方法区的运行时常量池;将类的静态变量以及运行时才能确定值的常量(如被 static final 修饰的引用类型变量)存于方法区的静态变量部分
  3. 随后进行类的验证、准备(为静态变量分配内存并赋初始值)、解析和初始化(调用类的 <clinit> 方法)。这里的解析不仅包括创建虚方法表,还会将符号引用转换为直接引用。虚方法是指类中除静态方法、private 方法、final 方法之外的方法,虚方法表记录着虚方法名和虚方法字节码的实际内存地址
  4. 之后在堆内存中创建子类对象,先对其属性中属于父类的部分赋值,对象头中有一个指针指向方法区中的类元数据信息
  5. 当对象调用方法(若是虚方法),会通过对象头指针找到其真正所属的类,然后在该类的虚方法表中查找此方法。若找到,依据虚方法表中的地址定位字节码文件;若未找到,会根据类的继承关系查找其父类的虚方法表,这就是动态链接的过程。程序计数器会记录下一条要执行的字节码指令相对于字节码文件的偏移量

在执行方法时,数据值的查找有三种情况: 

  1. 若使用形参或方法内定义的变量,会在栈帧的局部变量表中查找。局部变量表的大小在编译成字节码文件时就已确定,方法入栈时,栈帧会为其分配空间
  2. 若使用对象的实例变量,会根据对象在堆内存中的地址定位该对象,因为实例变量存储在堆内存的对象里,可直接获取使用
  3. 若使用类变量,会到对象所属实际类在方法区的静态变量部分获取值

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com