GraalVM 24 正式发布阿里巴巴贡献重要特性 —— 支持 Java Agent 插桩

本文涉及的产品
可观测监控 Prometheus 版,每月50GB免费额度
应用实时监控服务-用户体验监控,每月100OCU免费额度
应用实时监控服务-应用监控,每月50GB免费额度
简介: 阿里巴巴是 GraalVM 全球顾问委员会的唯一中国代表,阿里云程序语言与编译器团队和可观测团队合作实现了 GraalVM 应用的无侵入可观测能力,并在 ARMS 平台上线了该功能。目前在 GraalVM 24 中发布的是支持 Java agent 的第一步,其余能力将在 GraalVM 的后续版本中陆续发布。

作者:林子熠、饶子昊

image.png


2025 年 3 月 18 日 Oracle 双箭齐发,正式发布了 JDK 24 和 GraalVM 24,带来了众多新特性。


JDK 24 在性能和安全性方面均有改进特性列表链接见下,其中较大的一处改动是在 JDK 中用新的 Class-File API 取代了 ASM 接口,使 Java agent 在动态修改 Java 字节码时更加方便快捷。与之相呼应,GraalVM 24 在提升运行时性能、降低 native image 制品大小、提升调试体验等各方面的改进和提升之外特性列表链接见下,也迈出了在 native image 中静态化支持 Java agent 插桩的第一步。这就是在发布中提到的 Premain Support for Java Agents 新特性,即支持 Java agent 的 premain 机制。


这是由阿里巴巴贡献到 GraalVM 社区的新特性。阿里巴巴是 GraalVM 全球顾问委员会的唯一中国代表,阿里云程序语言与编译器团队和可观测团队合作实现了 GraalVM 应用的无侵入可观测能力,并在 ARMS 平台上线了该功能。目前在 GraalVM 24 中发布的是支持 Java agent 的第一步,其余能力将在 GraalVM 的后续版本中陆续发布。


实现原理


Java agent 是一种动态修改 Java 运行时代码的技术,无需应用程序修改任何内容,由 Java agent 在运行时修改实际要执行的内容,广泛使用于 Java 应用监控领域。Java 应用在上线后一般都会接入以 Java agent 为核心的可观测平台,监测运行时行为。


Java agent 的实现有两点基础,GraalVM 都不具备:


1. JVM 的 premain 机制。如果希望应用在运行时自始至终用到的都是经过变换的类,那么就需要在应用正式开始前就把修改类的需求告诉 JVM,然后在首次加载类时进行修改。Java 规范要求 agent 必须要提供名为 premain 的函数,在里面实现注册变换、选项解析、上下文环境初始化等工作。JVM 则提供了相应的执行入口,保证在执行主函数之前会调用各个 agent 的 premain 函数。但是在 GraalVM 的运行时中并没有设计过该机制,所以 agent 就不会有被调用的机会。


2. 对 Java 的字节码进行变换。修改字节码,改变目标的运行时行为。在 JDK24 之前基于 ASM 接口修改,在 JDK24 之后基于 Class-File 接口。GraalVM 将 Java 应用编译为 native 应用后不再保留字节码,因此失去了可以修改的目标,而且 native 应用本身也不支持动态修改。


GraalVM 因为不能支持 Java agent 而失去了可观测能力,这一功能缺失阻碍了很多用户适配 GraalVM。


我们在 GraalVM 上实现对 Java agent 的支持就是解决了以上两个问题:


首先,在 GraalVM 的编译时识别用户的 premain 函数,将它们加入编译队列,然后注册到运行时的 premain 入口。这样编译制品 native image 就会在运行时成功找到 premain 函数,然后执行其中的业务逻辑。这次在 GraalVM 24 中发布的就是这部分功能。


其次,将 Java agent 的类转换动作从运行时提前到编译时。因为基于 premain 的 agent 即使在 JVM 中,也是在首次加载目标类的时候对其进行变换,然后将变换好的结果返回给类加载器的。使用者首次见到的类就是变换后的,那么对于使用者来说,编译时变换和运行时变换就是等价的。所以我们只要将 agent 转换好的类编译进 native image 就可以了。那么问题就转换为如何在编译时获得 agent 变换后的类。


关于这个问题,我们的实现思路是先让挂载 agent 的 Java 应用执行一次,在此过程中把经过 agent 转换的类转储到磁盘,然后在编译时使用这些类。


通过ARMS对GraaIVM应用进行观测


目前,阿里云应用实时监控服务平台 ARMS(复制至浏览器打开或文末阅读原文直达:https://www.aliyun.com/product/arms已经基于上述方案,完成了相关能力支持,具体使用 ARMS 对 GraalVM 应用进行可观测的方法请参考 ARMS 官方文档(链接见文末)


当完成静态编译后,相关可执行 Native Image 文件中就包含了 ARMS 可观测 Java Agent 的代码。执行按照正常 GraalVM 应用部署运行方式进行运行即可,以下是其在 ARMS 控制台上的部分可观测数据采集效果:


GraalVM 应用指标数据采集效果


image.png


GraalVM 应用调用链数据采集效果


如下图是一个通过 Spring Schedule 发起定时任务调用 Restful 接口,然后通过 HttpClient 对外进行调用的示例:


image.png


性能效果


我们基于上述方案,也对 GraalVM 应用在启动速度和运行时内存占用进行了一些测试验证,发现 Java 应用基于 GraalVM 静态编译后,不仅可以正常使用开箱即用的可观测能力,运行时内存占用和启动延时仍然有巨大的优化效果(以下测试在 32 vCPU/64 GiB/5 Mbps 环境中完成)。


image.png


总结


GraaLVM 24 正式发布了由阿里巴巴贡献的 premain 机制,拉开了对 Java agent 的静态编译支持大幕。尽管 GraalVM 社区对无侵入式可观测的支持还处于早期阶段,但阿里云 ARMS 平台已经上线了完整的静态编译可观测能力支持。欢迎对上述相关产品能力和技术方案感兴趣的读者试用 ARMS,希望获取相关资料和做进一步交流探讨的读者请加钉钉群(群号: 80805000690)。


相关链接(复制链接至浏览器打开)


1.GraalVM 24 特性列表链接:

https://www.graalvm.org/release-notes/JDK_24/


2.JDK 24 特性列表链接:

https://jdk.java.net/24/release-notes


3.Class-File API:

https://openjdk.org/jeps/484


4.GraalVM 应用接入 ARMS 链接:

https://help.aliyun.com/zh/arms/application-monitoring/use-cases/connect-graalvm-applications-to-arms


5.使用 ARMS 对 GraalVM 应用进行可观测方法:

https://help.aliyun.com/zh/arms/application-monitoring/use-cases/connect-graalvm-applications-to-arms

目录
打赏
0
22
23
2
12731
分享
相关文章
从理论到实践:使用JAVA实现RAG、Agent、微调等六种常见大模型定制策略
大语言模型(LLM)在过去几年中彻底改变了自然语言处理领域,展现了在理解和生成类人文本方面的卓越能力。然而,通用LLM的开箱即用性能并不总能满足特定的业务需求或领域要求。为了将LLM更好地应用于实际场景,开发出了多种LLM定制策略。本文将深入探讨RAG(Retrieval Augmented Generation)、Agent、微调(Fine-Tuning)等六种常见的大模型定制策略,并使用JAVA进行demo处理,以期为AI资深架构师提供实践指导。
295 73
|
7月前
|
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
86 3
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【10月更文挑战第17天】Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
144 2
|
2月前
|
Java静态代码块深度剖析:机制、特性与最佳实践
在Java中,静态代码块(或称静态初始化块)是指类中定义的一个或多个`static { ... }`结构。其主要功能在于初始化类级别的数据,例如静态变量的初始化或执行仅需运行一次的初始化逻辑。
78 4
拥抱 OpenTelemetry:阿里云 Java Agent 演进实践
本文介绍了阿里云 Java Agent 4.x 版本在基于 OTel Java Agent 二次开发过程中的实践与思考,并重点从功能、性能、稳定性、兼容性四个方面介绍了所做的工作。同时也介绍了阿里云可观测团队积极参与开源建设取得的丰厚成果。
571 27
拥抱 OpenTelemetry:阿里云 Java Agent 演进实践
拥抱 OpenTelemetry:阿里云 Java Agent 演进实践
拥抱 OpenTelemetry:阿里云 Java Agent 演进实践
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
157 6
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
66 4
|
7月前
|
优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。
【10月更文挑战第19天】本文介绍了如何优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。内容包括Map的初始化、使用Stream API处理Map、利用merge方法、使用ComputeIfAbsent和ComputeIfPresent,以及Map的默认方法。这些技巧不仅提高了代码的可读性和维护性,还提升了开发效率。
238 3
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等