网站首页 > 精选文章 正文
引入
Java的编译器先将其编译为class文件,也就是字节码,这一步称为Javac编译;然后将字节码交由jvm(java虚拟机)解释执行,因而很多地方说“java是一种半编译、半解释执行”的语言。当然现在由于JIT的出现,这种说法有部分是错误的。接下来的两篇博客,会简略介绍一下Javac 编译过程和JIT机制。
Javac编译器将.java文件编译成为.class文件的过程,这里的Javac编译器称为前端编译器;相对应的还有后端编译器,它在程序运行期间将字节码转变成机器码。
Javac编译(前端编译)包括 词法、语法分析 、填充符号表 、语义分析、字节码生成。
词法、语法分析
词法分析是将源代码的字符流转变为标记(Token)集合。单个字符是程序编写过程中的的最小元素,而标记则是编译过程的最小元素,关键字、变量名、字面量、运算符等都可以成为标记。例如,下面这行代码
int num = a + 6;
这行代码包含了6个标记,分别是 int 、 num 、 = 、 a 、+ 、 6;
这里的整型标志int虽然由三个字符构成,但是它只是一个标记,不可拆分。
词法分析的作用是将Java源文件的字符流转变成对应的Token系列。而语法分析是将词法分析生成的Token序列来构建更加结构化的抽象语法树的过程。
抽象语法树是一种用来描述程序代码语法结构的树形表示方式,语法树的每一个节点都代表着程序代码中的一个语法结构,例如包、类型、修饰符、运算符、接口、返回值甚至代码注释等都可以是一个语法结构。语法分析过程由
com.sun.tools.javac.parser.Parser类实现,这个阶段产出的抽象语法树由
com.sun.tools.javc.tree.JCTree类表示。
经过这个步骤之后,编译器就基本不会再对源码文件进行操作了,后续的操作都是建立在抽象语法树上。
填充符号表
符号表是由一组符号地址和符号信息构成的表格。在目标代码生成阶段,对符号名进行地址分配时,符号表是地址分配的依据。
可以把它想象成哈希表K-V值对,或者JavaScript中键值对的形式。
一个类除了类本身会定义一些符号变量如类名称、变量名称和方法名称等,还有一些符号是引用其它类的,这些符号会调用其它类的方法或者变量等,还有一些类可能会继承或者实现超类和接口等。这些符号都是在其他类中定义的,那么就需要将这些类的符号也解析到符号表中。
记载的信息通常是标识符(identifier)的相关信息,如类型,作用域等。它通常会在语义分析(Semantic Analysis)阶段运用到,如我们在语法分析(Syntax Analysis)阶段是不会处理这样的情况的:
int a
a =
而这种情况,我们则可以在语义分析分析阶段,利用Symbol Table进行处理,识别出类型的不匹配情况。
语义分析
语法树能表示一个结构正确的源程序的抽象,但无法保证源程序是符合逻辑的。而语义分析的主要任务是读结构上正确的源程序进行上下文有关性质的审查。 语义分析过程分为标注检查和数据及控制流分析两个步骤:
- 标注检查步骤检查的内容包括诸如变量使用前是否已被声明、变量和赋值之间的数据类型是否匹配等。
- 数据及控制流分析是对程序上下文逻辑更进一步的验证,它可以检查出诸如程序局部变量在使用前是否有赋值、方法的每条路径是否都有返回值、是否所有的受查异常都被正确处理了等问题。
字节码生成
字节码生成阶段不仅仅是把前面各个步骤所生成的信息转化成字节码写到磁盘中,编译器还进行了少量的代码添加和转换工作。 实例构造器方法和类构造器方法就是在这个阶段添加到语法树之中的。
字节码生成结束后,.java文件就变成.class文件了,在执行Java程序时 ,字节码由JVM逐条解释执行。不过这是在JIT出现之前的情况了,下篇将介绍JIT。
笔者也是边学边写,如有错误,请在评论中指正。
猜你喜欢
- 2025-07-01 Java中的native方法(native java api)
- 2025-07-01 JAVA工程师面试考试测试题(Java面试题HR必备)
- 2025-07-01 干货 | Java语言这10个语言特性你知道吗?
- 2025-07-01 JavaCPP快速入门(官方demo增强版)
- 2025-07-01 Java编程入门第一课:HelloWorld(java编程如何入门)
- 2025-07-01 JVM系列之ClassLoader(jvm classloader)
- 2025-07-01 深入理解Java虚拟机之自己编译JDK
- 2025-07-01 函数入口一定是main吗?为什么不指定编译生成文件名, 默认是a.out?
- 2025-07-01 新手小白学Java|零基础入门笔记|原来学Java可以这么简单
- 2025-07-01 15.将一个给定的PDF文档拆分为多个文档(JAVA+PDFBOX)
- 07-03CentOS7系统如何修改主机名(更改centos主机名)
- 07-03Ubuntu1804 及以上版本的 Coredump 相关设置
- 07-03Linux中如何修改ip地址?(linux系统怎么更改ip地址)
- 07-03Linux系统日常运维九大核心技能(linux运维都干什么)
- 07-03Linux 日志管理攻略:用 journalctl 揪出服务器安全隐患
- 07-03Linux下快速安装ollama和deepseek并使用web界面
- 07-03RockyLinux9.5下使用ollama搭建本地AI大模型DeepSeek
- 07-03Linux 下的 PM2 完整指南(linux /media)
- 最近发表
-
- CentOS7系统如何修改主机名(更改centos主机名)
- Ubuntu1804 及以上版本的 Coredump 相关设置
- Linux中如何修改ip地址?(linux系统怎么更改ip地址)
- Linux系统日常运维九大核心技能(linux运维都干什么)
- Linux 日志管理攻略:用 journalctl 揪出服务器安全隐患
- Linux下快速安装ollama和deepseek并使用web界面
- RockyLinux9.5下使用ollama搭建本地AI大模型DeepSeek
- Linux 下的 PM2 完整指南(linux /media)
- Rocky Linux 9常用命令备忘录(不定时更新)
- Rocky Linux 9 系统初始化与安全加固脚本
- 标签列表
-
- 向日葵无法连接服务器 (32)
- git.exe (33)
- vscode更新 (34)
- dev c (33)
- git ignore命令 (32)
- gitlab提交代码步骤 (37)
- java update (36)
- vue debug (34)
- vue blur (32)
- vscode导入vue项目 (33)
- vue chart (32)
- vue cms (32)
- 大雅数据库 (34)
- 技术迭代 (37)
- 同一局域网 (33)
- github拒绝连接 (33)
- vscode php插件 (32)
- vue注释快捷键 (32)
- linux ssr (33)
- 微端服务器 (35)
- 导航猫 (32)
- 获取当前时间年月日 (33)
- stp软件 (33)
- http下载文件 (33)
- linux bt下载 (33)