Java 程序的运行原理

Java程序运行时,主要分为编译和运行两个步骤。首先将java的源文件编译成字节码。然后通过不同的虚拟机解释执行,实现跨平台

Java编译过程#

在Java中,类的编译是指将源代码文件(.java文件)转换为字节码文件(.class文件)的过程。这个过程一般由Java编译器(javac)完成,它会将源代码文件编译成可由Java虚拟机(JVM)执行的字节码文件。编译阶段通常是在开发人员编写完源代码后手动触发的,或者在集成开发环境(IDE)中自动触发

可以这样理解,编译的过程就是”编“和”译“。

编:将java源代码的结构组织成合适的格式,包括编译过程中的抽象语法树和符号表等,并在最终将源码编码成为class文件。

译:对源代码中的语义进行解析,并准确地翻译成另一种形式(字节码)。这一步既要确保原格式正确(Java源代码中的语法正确),又要确保翻译后的字节码跟源代码表达的意思一致。

也就是说,编译的过程要保证 输入的格式符合Java语言规范,输出的格式符合Java虚拟机规范

Java代码编译是由Java源码编译器来完成,流程图如下所示:

Java 源码编译由以下三个过程组成:(javac –verbose 输出有关编译器正在执行的操作的消息)

语法分析和输入到符号表

注解处理和语义分析

标准检查和生成class文件

最后生成的class文件由以下部分组成:

1、结构信息。包括class文件格式版本号及各部分的数量与大小的信息

2、元数据。对应于Java源码中声明与常量的信息。包含类/继承的超类/实现的接口的声明信息、域与方法声明信息和常量池

3、方法信息。对应Java源码中语句和表达式对应的信息。包含字节码、异常处理器表、求值栈与局部变量区大小、求值栈的类型记录、调试符号信息

Java执行过程#

在程序运行时,Java虚拟机(JVM)会负责加载这些.class文件并执行其中的字节码,这个过程也叫做类加载。在经过类加载(加载、链接、初始化)后将类加载到jvm内存中。

类加载过程

  1. 加载(Loading):在加载阶段,JVM会查找并加载.class文件。这个过程通常是通过类加载器(ClassLoader)来完成的。类加载器会根据类的全限定名(包括包名)在文件系统或网络中查找相应的.class文件,并将其加载到内存中。

  2. 链接(Linking):在链接阶段,JVM会将加载的类与当前运行的程序连接起来。这个过程包括三个步骤:验证(Verification)、准备(Preparation)和解析(Resolution)。在验证阶段,JVM会检查字节码文件的合法性和安全性。在准备阶段,JVM会为类的静态变量分配内存空间并设置默认初始值。在解析阶段,JVM会将类、方法和字段的符号引用解析为直接引用。

  3. 初始化(Initialization):在初始化阶段,JVM会执行类构造器()方法,这个方法是由编译器自动生成的,用于执行类的静态变量赋值和静态代码块。这个阶段是类加载的最后一个阶段,同时也是类加载过程中最重要的一个阶段。

程序的执行

JVM是基于栈的体系结构来执行class字节码的。线程创建后,都会产生程序计数器(PC)和栈(Stack),程序计数器存放下一条要执行的指令在方法内的偏移量,栈中存放一个个栈帧,每个栈帧对应着每个方法的每次调用,而栈帧又是有局部变量区和操作数栈两部分组成,局部变量区用于存放方法中的局部变量和参数,操作数栈中用于存放方法执行过程中产生的中间结果。

JVM内存结构图

总结#

在执行Java程序中,主要分为两部分;编译和解析执行

编译主要是对java文件语法、语义和语法糖等检查。并生成字节码文件

解析执行主要是对java类进行类加载和内存分配,然后通过通过栈帧的方式来驱动程序执行

① Java 源文件—->编译器—->字节码文件
② 字节码文件—->JVM—->机器码

Q&A#

main方法的执行过程 #

通过java命令执行这个程序时,会通过环境变量配置路径找到java执行程序(c++),它的内部会启动一个Java虚拟机实例。在Java中,public static void main(String[] args)是程序的入口点,这是因为Java虚拟机(JVM)在执行程序时会寻找这个特定的方法签名来作为程序的入口点。这个方法的签名是固定的,它必须是public(公共的,可以被外部访问)、static(静态的,不需要实例化即可调用)、void(无返回值)类型,并且方法名必须是main,参数列表必须是一个字符串数组。

执行程序时JVM会首先加载并初始化指定的类,然后寻找这个特定的main方法,并且执行其中的代码。这是Java程序启动时的入口点,它负责启动程序的执行过程。

另外,main方法的参数args是用来接收命令行参数的,这使得Java程序可以接受外部传入的参数,从而实现更灵活的程序设计和执行。因此,public static void main(String[] args)是Java程序的入口点,负责程序的启动和执行。

编译器查看class为什么不是编译后的代码#

IDEA 默认会使用 Fernflower 对字节码文件进行反编译,可以看到javac会帮助我们对源文件进行一些编译优化

posted @   糯米๓  阅读(80)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示