当前位置: 首页 > Web前端 > HTML5

我听说你不知道Java代码是如何工作的?

时间:2023-04-05 20:19:30 HTML5

前言作为一名Java程序员,我们需要知道Java代码是如何工作的。最近看了《深入理解Java虚拟机》这本书,做了一些笔记。希望对大家有所帮助。如果有任何不准确的地方,请随时指出。我很感激。在这里,小编建了一个前端学习交流按钮群:132667127,自己整理的最新前端资料和进阶开发教程。有兴趣的可以进群一起学习交流java代码运行的主要流程。本文主要讲解过程。如下:java源文件编译成类字节码。类加载器将字节码加载到虚拟机的方法区。对象方法调用是在运行时创建的,执行引擎将它们解释为机器代码。CPU执行指令、多线程和切换上下文。我们都知道java代码运行在Java虚拟机上。但是java是一种面向对象的高级语言。它的语法不仅非常复杂,而且抽象度也非常高,不能直接在计算机硬件上运行。Java虚拟机(JavaVirtualMachine,简称JVM)是??一台运行所有Java程序的抽象计算机,是Java语言的运行环境。因此,在运行Java程序之前,需要编译器将代码编译成Java虚拟机可以识别的指令程序。这就是Java字节码,也就是类文件。因此,运行Java代码的第一步就是将Java源代码编译成.class字节码文件。类加载Class文件中描述的各种信息需要加载到虚拟机中才能运行和使用。因此,需要将class字节码文件加载到Java虚拟机中。虚拟机从Class文件中加载描述类的数据到内存中,并对数据进行校验、转换、解析、初始化,最终形成虚拟机可以直接使用的Java类型。这就是虚拟机的类加载机制。加载在加载阶段,虚拟机需要完成以下三件事:通过类的全限定名获取定义该类的二进制字节流。将这个字节流表示的静态存储结构转换成方法区的运行时数据结构。在内存中生成一个代表该类的java.lang.Class对象,作为该类各种数据在方法区的访问入口。加载阶段完成后,这些二进制字节流按照虚拟机要求的格式存放在方法区中。中间。验证为了保证Class文件的字节流所包含的信息符合当前虚拟机的要求,不会危及虚拟机的安全,Java虚拟机对输入的字节流进行验证过程。验证阶段包括四个阶段:文件格式验证、元数据验证、字节码验证和符号引用验证。文件格式校验:校验字节流是否符合Class文件格式规范,如:是否以幻数0xCAFEBABE开头。元数据校验:对字节码描述的信息进行语义分析,如:本类的父类是否继承了不允许继承的类(final修饰的类);字节码验证:主要目的是通过对数据流和控制流的分析,判断程序语义是否合法、合乎逻辑。例如:保证跳转指令不会跳转到方法体之外的字节码指令。符号引用验证:发生在虚拟机将符号引用转换为直接引用时,例如:验证符号引用中字符串描述的完全限定名是否可以找到对应的类。准备准备阶段是正式为类变量分配内存,并设置类变量的初始值。这些变量使用的内存将分配在方法区中。例如:publicstaticintvalue=123;准备阶段后变量值的初始值为0,而不是123。解析解析阶段是虚拟机将常量池中的符号引用替换为直接引用的过程。例如:com.User类引用com.Tool类。编译时User类并不知道Tool类的实际内存地址,所以只能用符号com.Tool来表示(假设)。类加载加载User类时,可以通过虚拟机获取Tool类的实际内存地址,所以可以将符号com.Tool替换为Tool类的实际内存地址,即直接引用地址.解析动作主要针对七类符号引用进行:类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符。初始化在初始化阶段,真正执行类中定义的Java字节码。在这个阶段,类变量和其他资源根据程序员通过程序制定的主观计划进行初始化。Java虚拟机在创建对象时是如何执行字节码的?让我们首先看看在运行时创建对象。Java是一种面向对象的程序设计语言,程序的运行是以对象为调用单位的。字节码文件加载到虚拟机的方法区后,在程序运行过程中通过class字节码文件创建对应的对象信息。创建对象的方式有:new关键字、反射等。Java堆内存是线程共享的一块区域,创建的对象信息存储在Java堆内存中。方法调用JVM的调用单元是对象,但真正执行功能的代码仍然是对象上的方法。在运行过程中,每当调用一个java方法时,java虚拟机都会在当前线程的java方法栈中生成一个栈帧,用于存放局部变量和字节码操作数。方法栈内存是线程私有的,每个线程都有自己的方法栈。如果对应的方法是native方法,那么对应的方法就是native方法栈。java运行时数据区如下:说明当调用Java对象的方法时,JVM执行引擎会将方法的字节码文件翻译成计算机可以识别的机器码,机器码信息存放在方法区。翻译有两种方式:解释执行和即时编译。两种翻译方式的区别在于:解释执行一行代码,解释一行。大多数不常用的代码都使用这种方法。即使是针对一些热点代码进行编译,将一个方法中包含的字节码全部翻译成机器指令,以提高java虚拟机的运行效率。即时编译基于经典的80/20规则,即20%的代码占用80%的计算资源。执行指令Java程序加载到内存后,指令也在内存中。指令的指令寄存器IP指向下一条要执行的指令的地址。CPU的控制单元根据IP寄存器的指针,将主存中的指令加载到指令寄存器中。这些加载的指令是一串二进制代码,需要通过解码器进行解码。译码后,如果需要获取操作数,则从内存中取出数据,调用运算器进行计算。多线程上下文切换CPU一旦上电,就会反复从内存中获取指令,解码并执行。为了支持多任务,CPU将执行时间资源划分成时间片,每个程序执行一段时间。java虚拟机的多线程是通过轮流切换线程来分配处理执行时间来实现的。在任何给定时刻,一个处理器(多核处理器的一个核心)将只执行一个程序。操作说明。假设当前线程正在运行,CPU分配的时间已经执行完毕,那么需要保存运行结果信息,否则之前的工作就白费了。因此,程序计数器(PC寄存器)的作用就体现出来了,它是一个小线程私有的内存空间,可以看作是当前线程执行的字节码的行号指示器。当CPU分配时间让它再次运行时,可以恢复数据,然后可以从上次执行的位置继续执行。