javac 编译java文件源码 怎么生成 ast语法树 步骤详解

javac 中,编译源代码并生成抽象语法树(AST)是一个多步骤的过程,涉及从源码解析到最终生成字节码。以下是详细步骤,描述了如何使用 javac 编译源码并生成 AST。

1. 准备源文件

javac 首先需要源文件。这些源文件是包含 Java 源代码的 .java 文件。当你调用 javac 命令时,通常会传递这些源文件作为参数,或者通过某种方式将它们传递给编译器。

2. 创建 Java Compiler 实例

javac 编译过程的核心是 JavaCompiler 类。在内部,javac 使用了 JavacTask 来执行编译任务。

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

通过调用 ToolProvider.getSystemJavaCompiler() 方法,获得一个编译器实例,该实例提供了编译方法。

3. 设置编译选项和上下文

在调用编译器前,你可以设置许多编译选项(例如是否启用注解处理器,是否生成调试信息等)。这些选项存储在 Context 中,这是 Javac 的一个重要组件,用于存储编译过程中的状态。

Context context = new Context(); JavacFileManager.preRegister(context);

上下文(Context)是一个依赖注入容器,它持有与编译过程相关的各种对象,包括日志、文件管理器、选项等。

4. 解析命令行选项

javac 接收到命令行参数后,会解析这些参数并根据需要设置不同的选项。命令行选项通常包括目标类路径、输出目录、调试信息等。

例如,CommandLine.parse() 负责将命令行选项解析为 Arguments 对象。

5. 初始化 Log 对象

Logjavac 用来记录编译过程中消息、错误和警告的地方。在编译开始之前,必须创建并初始化 Log 对象。

log = Log.instance(context);

Log 处理所有与编译相关的输出信息,包括错误、警告和调试信息。

6. 文件解析(Parse)

javac 中,源代码的解析过程是通过 Parser 完成的。Parser 将源代码转换为一个或多个 JCCompilationUnit(这是 JCTree 的子类),它是 Java 源代码的抽象语法树(AST)的根节点。

parseFiles() 方法会遍历所有源文件,调用 Parser 类来解析每个文件并生成相应的语法树。

public List<JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects) {ListBuffer<JCCompilationUnit> trees = new ListBuffer<>();for (JavaFileObject fileObject : fileObjects) {trees.append(parse(fileObject));}return trees.toList();
}

parse(fileObject) 是具体的解析步骤,它会调用 Parser.parseCompilationUnit(),生成一个 JCCompilationUnit 对象。这个对象代表了一个编译单元(即整个 Java 文件)的语法结构。

public JCTree.JCCompilationUnit parse(JavaFileObject filename) {JavaFileObject prev = log.useSource(filename);try {JCTree.JCCompilationUnit t = parse(filename, readSource(filename));if (t.endPositions != null)log.setEndPosTable(filename, t.endPositions);return t;} finally {log.useSource(prev);}
}

其中,Parser.parseCompilationUnit() 会将源码字符串转换为一个抽象语法树(AST)。在这里,JCCompilationUnit 是整个文件的抽象表示,它包括了文件中的所有类型声明、包声明和导入声明。

7. 抽象语法树(AST)的构建

Parser 类在解析过程中会生成一个 JCTree 类型的树。JCTree 是所有语法树节点的基类。每个 Java 源文件会产生一个 JCCompilationUnit,其中包含多个不同的 AST 节点(例如类、方法、字段等)。

public JCTree.JCCompilationUnit parseCompilationUnit() {ListBuffer<JCTree> defs = new ListBuffer<>();while (token.kind != EOF) {// Process each part of the source codedefs.append(typeDeclaration(mods, docComment));}return F.at(firstToken.pos).TopLevel(defs.toList());
}

parseCompilationUnit 方法中,defs 是一个 ListBuffer<JCTree>,用于存储文件中的各个语法节点。它会遍历源码中的每个声明(如类、方法、字段等),并将其转换为相应的 JCTree 节点。

8. 生成和返回 AST

解析过程完成后,会返回一个 JCCompilationUnit 对象,它是当前源文件的 AST 根节点。你可以通过访问这些节点,来获取 Java 源代码的结构。

JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(defs.toList());

这个 JCCompilationUnit 对象包含了整个源文件的结构,可以通过遍历其树形结构,查看其中的类、方法、字段、注解等元素。

9. 注解处理器(可选)

如果在编译过程中需要处理注解,javac 会触发注解处理器的执行。你可以在 JavacTask 中配置注解处理器。注解处理器的任务通常是解析源代码中的注解并生成新的代码或其他资源。

AnnotationProcessorFactory annotationProcessorFactory = ...; compiler.getTask(...).setProcessors(Collections.singletonList(annotationProcessorFactory));

10. 生成字节码(字节码生成阶段)

一旦 AST 构建完成,javac 会进行类型检查、代码生成、优化等步骤,最终生成字节码。这部分内容虽然在构建 AST 之前已经开始,但最终的字节码生成会依赖于 AST 的正确性。

总结

  • javac 编译源代码的过程首先将源文件加载到 JavaFileObject 中。
  • 使用 Parser 将这些源文件解析为 JCCompilationUnit,这是 AST 的根节点。
  • JCCompilationUnit 包含文件中的所有类、方法、字段和其他结构。
  • 解析后的 AST 可以用于进一步的代码分析、优化或生成字节码。

javac 的 AST 是通过一系列的解析器和内部数据结构实现的,主要依赖 JCTree 类的层次结构来表示源代码的各种构造。

 ##附录-调试截图

调试堆栈

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/64679.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手游和应用出海资讯:怪物猎人AR手游累计总收入已超过2.5亿美元、SuperPlay获得迪士尼纸牌游戏发行许可

NetMarvel帮助游戏和应用广告主洞察全球市场、获取行业信息&#xff0c;以下为12月第一周资讯&#xff1a; ● 怪物猎人AR手游累计总收入已超过 2.5 亿美元 ● SuperPlay获得迪士尼纸牌游戏发行许可 ● 腾讯混元大模型上线文生视频能力 ● 网易天下事业部一拆三&#xff0c;蛋仔…

酷克数据携手江西移动入选“星河(Galaxy)”数据库潜力案例

2024 年 12 月 18 - 19 日&#xff0c;为推动打造行业交流平台&#xff0c;驱动产业创新共荣&#xff0c;大数据技术标准推进委员会以“数据重塑价值 智能链接未来”为主题&#xff0c;在北京召开为期两天的“2024 数据资产管理大会”。 在会上&#xff0c;第八届大数据“星河&…

Mysql语法之DQL查询的多行函数

Mysql的多行函数和分组 目录 Mysql的多行函数和分组多行函数概念常用的多行函数 数据分组概念语法where和having的区别 语句关键字及执行顺序语句关键字执行顺序 实际操作基本语句格式和多行操作筛选语句格式 多行函数 概念 不管函数处理多少条&#xff0c;只返回一条记录&…

Ubuntu22.04上安装esp-idf

一、安装准备# 建议使用Ubuntu 20.04 或 Ubuntu 22.04 操作系统 为了在 Ubuntu 22.04 中使用 esp-idf&#xff0c;需要安装一些依赖包 sudo apt-get install git wget flex bison gperf python3\python3-pip python3-venv cmake ninja-build ccache\libffi-dev libssl-dev dfu…

WPF 依赖属性和附加属性

除了普通的 CLR 属性&#xff0c; WPF 还有一套自己的属性系统。这个系统中的属性称为依赖属性。 1. 依赖属性 为啥叫依赖属性&#xff1f;不叫阿猫阿狗属性&#xff1f; 通常我们定义一个普通 CLR 属性&#xff0c;其实就是获取和设置一个私有字段的值。假设声明了 100 个 …

在linux系统的docker中安装GitLab

一、安装GitLab&#xff1a; 在安装了docker之后就是下载安装GitLab了&#xff0c;在linux系统中输入命令&#xff1a;docker search gitlab就可以看到很多项目&#xff0c;一般安装第一个&#xff0c;它是英文版的&#xff0c;如果英文不好可以安装twang2218/gitlab-ce-zh。 …

2024最新CF罗技鼠标宏

使用效果&#xff1a; 支持的功能 M4 7发一个点HK417 连点瞬狙炼狱加特林一个圈 下载链接 点击下载

JS CSS HTML 的代码如何快速封装

我们为什么要封装代码&#xff0c;是因为封装后的代码&#xff0c;会显得非常美观&#xff0c;减少代码的复用&#xff0c;方便我们更好的去维护代码&#xff0c;不用一个一个页面的去找去改&#xff0c;直接封装好的代码里面去改就可以了 目录 1.html代码封装 2.CSS代码封装…

使用docker拉取镜像很慢或者总是超时的问题

在拉取镜像的时候比如说mysql镜像&#xff0c;在拉取 时总是失败&#xff1a; 像这种就是网络的原因&#xff0c;因为你是连接到了外网去进行下载的&#xff0c;这个时候可以添加你的访问镜像源。也就是daemon.json文件&#xff0c;如果你没有这个文件可以输入 vim /etc/dock…

MySQL复制问题和解决

目录 环境介绍 一&#xff0c;主库执行delete&#xff0c;从库没有该数据 模拟故障 修复故障 二&#xff0c;主库执行insert&#xff0c;从库已存在该数据 模拟故障 故障恢复 三&#xff0c;主库执行update&#xff0c;从库没有该数据 模拟故障 故障恢复 四&#xf…

[RocketMQ] 发送重试机制与消费重试机制~

发送重试 RocketMQ 客户端发送消息时&#xff0c;由于网络故障等因素导致消息发送失败&#xff0c;这时客户端SDK会触发重试机制&#xff0c;尝试重新发送以达到调用成功的效果。 触发条件 客户端消息发送请求失败或超时。服务端节点处于重启或下线状态。服务端运行慢造成请…

mfc140u.dll是什么文件?如何解决mfc140u.dll丢失的相关问题

遇到“mfc140u.dll文件丢失”的错误通常影响应用程序的运行&#xff0c;这个问题主要出现在使用Microsoft Visual C环境开发的软件中。mfc140u.dll是一个重要的系统文件&#xff0c;如果它丢失或损坏&#xff0c;会导致相关程序无法启动。本文将简要介绍几种快速有效的方法来恢…

02-9.python入门基础一Python模块与包(一)

一、Python 模块的概念 &#xff08;一&#xff09;模块的基本定义 在 Python 中&#xff0c;模块&#xff08;Module&#xff09;是一种组织代码的基本单元&#xff0c;简单来说&#xff0c;一个以 .py 结尾的 Python 文件就是一个模块。例如&#xff0c;我们创建一个名为 ex…

当我用影刀AI Power做了一个旅游攻略小助手

在线体验地址&#xff1a;旅游攻略小助手https://power.yingdao.com/assistant/ca1dfe1c-9451-450e-a5f1-d270e938a3ad/share 运行效果图展示&#xff1a; 话不多说一起看下效果图&#xff1a; 智能体的截图&#xff1a; 工作流截图&#xff1a; 搭建逻辑&#xff1a; 其实这…

AI Agent与MEME:技术与文化融合驱动Web3创新

AI Agent如何引领Web3新时代&#xff1f; 随着Web3与区块链技术的迅速发展&#xff0c;AI Agent作为人工智能与区块链的交汇点&#xff0c;正在逐步成为推动去中心化生态的重要力量。同时&#xff0c;MEME文化凭借其强大的社区驱动力和文化渗透力&#xff0c;在链上生态中扮演着…

【STM32 Modbus编程】-作为主设备写入多个线圈和寄存器

作为主设备写入多个线圈和寄存器 文章目录 作为主设备写入多个线圈和寄存器1、硬件准备与连接1.1 RS485模块介绍1.2 硬件配置与接线1.3 软件准备2、写入多个线圈2.1 数据格式2.2 发送数据2.3 结果3、写入多个寄存器3.1 数据格式3.2 发送数据3.3 结果本文将实现STM32作为ModBus主…

Spring学习之——Sping-XML

一、Spring的概述 (一)什么是Spring? Spring是针对bean对象的生命周期进行管理的轻量级容器。提供了功能强大IOC、AOP及Web MVC等功能。Spring框架主要由七部分组成&#xff1a;分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 S…

电商商品详情API接口(item get)数据分析上货

电商商品详情API接口&#xff08;item get&#xff09;在数据分析与商品上货方面发挥着重要作用。以下是对这两个方面的详细探讨&#xff1a; 一、数据分析 数据源获取&#xff1a; 商品详情API接口提供了丰富的数据源&#xff0c;包括商品的标题、价格、库存、描述、图片、用…

EasyGBS国标GB28181平台P2P远程访问故障排查指南:客户端角度的排查思路

在现代视频监控系统中&#xff0c;P2P&#xff08;点对点&#xff09;技术因其便捷性和高效性而被广泛应用。然而&#xff0c;当用户在使用P2P远程访问时遇到设备不在线或无法访问的问题时&#xff0c;有效的排查方法显得尤为重要。本文将从客户端的角度出发&#xff0c;详细探…

win11 C盘出现感叹号解决方法

出现感叹号&#xff0c;原因是对C盘进行了BitLocker驱动器加密操作。如果想去除感叹号&#xff0c;对C盘进行BitLocker解密即可。 步骤如下&#xff1a; 1.点击Windows搜索框 2.搜索框内输入 系统 3.按下回车&#xff0c;进入系统界面 4.点击隐私和安全性 点击BitLocker驱…