前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java文件是怎么编译成Class文件的

Java文件是怎么编译成Class文件的

作者头像
向着百万年薪努力的小赵
发布2022-12-02 10:45:30
1.3K0
发布2022-12-02 10:45:30
举报
文章被收录于专栏:小赵的Java学习

其实就是我们前端的编译过程,是通过javac(编译器)把java文件变成.class字节码文件。

代码语言:javascript
复制
javac HelloWorld.java
javap -verbose HelloWorld.class
在这里插入图片描述
在这里插入图片描述

如上图所示,这里给出一个javac 源码中的 JavaCompiler.java

代码语言:javascript
复制
public void compile(List<JavaFileObject> sourceFileObjects, List<String> classnames, Iterable<? extends Processor> processors) {
	try {
		// 准备过程:初始化插入式注解处理器 
		initProcessAnnotations(processors);
		// These method calls must be chained to avoid memory leaks
		delegateCompiler = // 过程 2:执行注解处理器
			processAnnotations(
				// 过程 1.2:输出到符号表
				enterTrees(
					stopIfError(CompileState.PARSE,
						// 过程 1.1:词法分析、语法分析
						parseFiles(sourceFileObjects))),
						classnames);	
		// 过程 3:分析及字节码生成
		delegateCompiler.compile2();
		delegateCompiler.close();
		elapsed_msec = delegateCompiler.elapsed_msec;
	} catch (Abort ex) {
		if (devVerbose)
			ex.printStackTrace(System.err);
	} finally { 
		if (procEnvImpl != null)
			procEnvImpl.close();
	}
}

按照上图,逐步分析

1词法分析器

读取源代码,一个字节一个字节读取出来,找到这些词法中的语句比如:访问修饰符、类和类名、条件语句、循环结构、基础的语法等等。

结论:是将源代码的字符流转变为标记(Token)集合的过程,单个字符是程序编写时的最小元素,但标记才是编译时的最小元素。关键字、变量名、字面量、运算符都可以作为标记,如下代码:

代码语言:javascript
复制
int a = b + 2;

这句代码中就包含了7个标记,分别是int、a、=、b、+、2、;、虽然关键字int由3个字符构成,但是它只是一个独立的标记,不可以再拆分。在Javac的源码中,词法分析过程由 com.sun.tools.javac.parser.Scanner类来实现。

真正完成解析的是 JavaTokenizer.java的readToken();方法

2语法分析器

根据Token集合生成抽象语法树,抽象语法树(Abstract Syntax Tree,AST)是一 种用来描述程序代码语法结构的树形表示方式,抽象语法树的每一个节点都代表着程序代码中的一个 语法结构(SyntaxConstruct),例如包、类型、修饰符、运算符、接口、返回值甚至连代码注释等都 可以是一种特定的语法结构.

上述这段代码生成的抽象语法树如下( IDEA JDT AstView 插件可以查看抽象语法树):

在这里插入图片描述
在这里插入图片描述

上述抽象语法树在Java中使用com.sun.tools.javac.tree.JCTree类来表示。

经过词法和语法分析生成语法树以后,编译器就不会再对源码字符流进行操作了,后续的操作都建立在抽象语法树之上。

结论:检查Token集合是否符合Java语言规范,有没有语法的错误,一切通过校验后得到一颗抽象的语法树。

例如:if 后面是否跟着boolean表达式 ,Java 关键字是否正确等等。

3语义分析

经过语法分析之后,编译器获得了程序代码的抽象语法树表示,抽象语法树能够表示一个结构正确的源程序,但无法保证源程序的语义是符合逻辑的;

结论:而语义分析的主要任务则是对结构上正确的源程序进行上下文相关性质的检查,将比较复杂的语法语义转化成简单的语法,譬如进行变量类型检查、控制流检查、数据流检查。

对我们刚刚生成那颗抽象语法解析树进行变量类型检查、控制流检查、数据流检查,解语法糖。

解语法糖 通常来说使用语法糖能够减少代码量、增加程序的可读性,从而减少程序代码出错的机会。“低糖”的语法让Java程序实现相同功能的代码量往往高于其他语言,通俗地说 就是会显得比较“啰嗦”,所以才会出现 Kotlin。

解语法糖的过程由desugar()方法触发,在com.sun.tools.javac.comp.TransTypes类 和com.sun.tools.javac.comp.Lower类中完成。

4字节码生成

字节码生成是Javac编译过程的最后一个阶段,在Javac源码里面由com.sun.tools.javac.jvm.Gen类来 完成。字节码生成阶段不仅仅是把前面各个步骤所生成的信息(语法树、符号表)转化成字节码指令写到磁盘中,编译器还进行了少量的代码添加和转换工作。

比如:

  • 将static语句块、static变量收敛到方法中
  • 将实例变量初始化、调用父类构造器收敛到方法
  • 程序优化,比如将字符串的+操作替换成StringBuilder的append

完成了语法树的遍历和调整以后,就会填充了所有信息的符号表交给com.sun.tools.javac.jvm.ClassWriter类,最后由该类的writeClass()方法输出字节码。

结论:代码生成器的结果就是生成符合Java虚拟机规范的字节码

5 Class File 解析

这个里面东西属实太多而且繁杂,大家有兴趣了可以看看我的JVM专栏里的纸质笔记 链接: JVM学习专栏

链接: JVM学习笔记-Class类文件结构介绍——(纸质笔记)

链接: JVM学习笔记-Class类文件结构-魔数,版本号,常量池——(纸质笔记)

链接: JVM学习笔记-Class类文件结构-访问标志,类索引,父类索引,接口索引集合——(纸质笔记)

链接: JVM学习笔记-Class类文件结构-字段表,方法表集合——(纸质笔记)

链接: JVM学习笔记-Class类文件结构-属性表集合——(纸质笔记)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1词法分析器
  • 2语法分析器
  • 3语义分析
  • 4字节码生成
  • 5 Class File 解析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档