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

news2024/12/23 3:03:19

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 code
        defs.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.coloradmin.cn/o/2264013.html

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

相关文章

人工智能入门是先看西瓜书还是先看花书?

在人工智能入门时&#xff0c;关于先看《机器学习》&#xff08;西瓜书&#xff09;还是先看《深度学习》&#xff08;花书&#xff09;的问题&#xff0c;实际上取决于个人的学习目标和背景。 《机器学习》&#xff08;西瓜书&#xff09;由周志华教授撰写&#xff0c;是一本…

Linux 安装Nginx 并配置启动 (已实测)

文章目录 一、安装Nginx二、配置 Nginx 为系统服务 一、安装Nginx 安装依赖&#xff0c;确保Nginx编译和运行正常&#xff0c;打开终端执行以下命令 yum install -y wget gcc-c pcre-devel zlib-devel openssl-devel下载Nginx # 例如&#xff0c;下载Nginx 1.24.0版本 wget …

Linux 下的 GPT 和 MBR 分区表详解

文章目录 Linux 下的 GPT 和 MBR 分区表详解一、分区表的作用二、MBR&#xff08;Master Boot Record&#xff09;1. **特点**2. **优点**3. **缺点**4. **适用场景** 三、GPT&#xff08;GUID Partition Table&#xff09;1. **特点**2. **优点**3. **缺点**4. **适用场景** 四…

10. 虚拟机VMware Workstation Pro下共享Ubuntu和Win11文件夹

本文记录当前最新版虚拟机VMware Workstation Pro&#xff08;2024.12&#xff09;如何在win11下共享文件&#xff0c;以实现Windows与Ubuntu互传文件的目的。 1. 创建共享文件夹 1.1 先关闭虚拟机的客户机&#xff0c;打开虚拟机设置 1.2 在虚拟机设置界面找到“选项”->“…

有哪些免费的 ERP 软件可供选择?哪些 ERP 软件使用体验较好?

想找个 “免费” 的 ERP 软件&#xff1f; 咱得知道&#xff0c;ERP 那可是涉及财务、人力、供应链、采购、销售等好多方面的重要企业软件。功能这么全&#xff0c;能免费才怪呢&#xff01;真要是有免费的&#xff0c;早就火遍大江南北&#xff0c;说不定把市场都垄断了&…

2024 年的科技趋势

2024 年在科技领域有着诸多重大进展与突破。从人工智能、量子计算到基因组医学、可再生能源以及新兴技术重塑了众多行业。随着元宇宙等趋势的兴起以及太空探索取得的进步&#xff0c;未来在接下来的岁月里有望继续取得进展与突破。让我们来探讨一下定义 2024 年的一些关键趋势&…

python rabbitmq实现简单/持久/广播/组播/topic/rpc消息异步发送可配置Django

windows首先安装rabbitmq 点击参考安装 1、环境介绍 Python 3.10.16 其他通过pip安装的版本(Django、pika、celery这几个必须要有最好版本一致) amqp 5.3.1 asgiref 3.8.1 async-timeout 5.0.1 billiard 4.2.1 celery 5.4.0 …

厦门凯酷全科技有限公司短视频带货可靠吗?

在当今这个数字化时代&#xff0c;抖音作为短视频和直播带货的领军平台&#xff0c;已经吸引了无数商家的目光。而在这一片繁荣的电商蓝海中&#xff0c;厦门凯酷全科技有限公司&#xff08;以下简称“凯酷全”&#xff09;凭借其专业的团队、丰富的经验和创新的服务模式&#…

从源码分析swift GCD_DispatchGroup

前言&#xff1a; 最近在写需求的时候用到了DispatchGroup&#xff0c;一直没有深入去学习&#xff0c;既然遇到了那么就总结下吧。。。。 基本介绍&#xff1a; 任务组&#xff08;DispatchGroup&#xff09; DispatchGroup 可以将多个任务组合在一起并且监听它们的完成状态。…

在C#中使用资源保存图像和文本和其他数据并在运行时加载

资源是您可以构建到应用程序中的图像、字符串、文本文件和其他数据。您的程序可以在运行时加载资源以显示新图片、文本或其他内容。 要将资源添加到项目&#xff0c;请打开“项目”菜单并选择最底部的“属性”命令。在“属性”页面上&#xff0c;单击“资源”选项卡。现在&…

基于MATLAB的图像增强

目录 一、背景及意义介绍背景图像采集过程中的局限性 意义 二、概述三、代码结构及说明&#xff08;一&#xff09;整体结构&#xff08;二&#xff09;亮度增强部分&#xff08;三&#xff09;对比度增强部分&#xff08;四&#xff09;锐度增强部分 四、复现步骤&#xff08;…

电脑丢失dll文件一键修复的多种方法分析,电脑故障修复攻略

电脑在使用过程中&#xff0c;有时会遇到DLL文件丢失的情况&#xff0c;这可能导致软件无法正常运行或系统出现故障。当面对这种状况时&#xff0c;不必过于慌张&#xff0c;因为有多种有效的修复方法可供选择。下面我们一起来看看电脑丢失dll文件的多种解决方法。 一.了解什么…

android EditText密码自动填充适配

android上的密码&#xff08;其实不仅仅是密码&#xff0c;可以是用户名也可以是邮箱&#xff09;自动填充&#xff0c;是需要考虑适配的。 官方文档&#xff1a;https://developer.android.com/identity/autofill/autofill-optimize?hlzh-cn 什么是自动填充 手机厂商一般会…

GO--堆(have TODO)

堆 堆&#xff08;Heap&#xff09;是一种特殊的数据结构。它是一棵完全二叉树&#xff08;完全二叉树是指除了最后一层外&#xff0c;每一层上的节点数都是满的&#xff0c;并且最后一层的节点都集中在左边&#xff09;&#xff0c;结放在数组&#xff08;切片&#xff09;中…

Yolov11学习笔记

YOLOv11学习笔记 1.conda环境变量配置 1.1pycharm中新建conda虚拟环境 在win11系统中&#xff0c;创建的conda虚拟环境不会在conda的安装目录下&#xff0c; 而是会在C:\Users\Admin.conda\envs 比如我的anaconda安装目录在F:\anaconda3 但是生成的虚拟环境在C:\Users\Adm…

算法 计算大的长方形容器中,存放一排小长形容器,计算出小长形容器中最后一个元素的x坐标的位置的实现方法

1、先上个图&#xff1a; 2、说明 1&#xff09;中间的蓝色长方形是里面的橙色长方形的容器&#xff0c;比如第一个图中width2width3&#xff0c;因为只有一个&#xff0c;第二个图中有二个小的长方形&#xff0c;也就是说width22width3&#xff0c;第三个图中有3个小长方形&a…

不同版本的 Redis 的键值对内存占用情况示例

不同版本的 Redis 的键值对内存占用情况示例 文章目录 不同版本的 Redis 的键值对内存占用情况示例Redis 6.0redisObjectdictEntrysds&#x1f340; 数据结构&#x1f340; sdslen() 函数&#x1f340; sdsReqType() 函数&#x1f340; sdsHdrSize() 函数 内存分配 - malloc() …

捕虫游戏-项目制作

前言 同学们前面已经学习了html css javascript基础部分了&#xff0c;为了巩固和熟练前面所学的知识&#xff0c;从今天起&#xff0c;我们要做一个捕虫游戏的项目。通过项目实战夯实基础&#xff0c;将所学的知识真正用到实战中&#xff0c;强化对网页设计的能力&#xff…

用docker快速安装电子白板Excalidraw绘制流程图

注&#xff1a;本文操作以debian12.8 最小化安装环境为host系统。 一、彻底卸载原有的残留 apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras 二、设置docker的安装源 # Add Dockers official G…

【从零开始入门unity游戏开发之——C#篇23】C#面向对象继承——`as`类型转化和`is`类型检查、向上转型和向下转型、里氏替换原则(LSP)

文章目录 一、as类型转化和is类型检查1、as 关键字使用场景&#xff1a;语法&#xff1a;示例&#xff1a;特点&#xff1a; 2、is 关键字使用场景&#xff1a;语法&#xff1a;示例&#xff1a;特点&#xff1a; 3、总结 二、向上转型和向下转型1、向上转型示例&#xff1a; 2…