JVM工作原理与实战(三十六):GraalVM虚拟机

本文涉及的产品
函数计算FC,每月15万CU 3个月
简介: JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了GraalVM、GraalVM的两种运行模式、GraalVM应用场景、参数优化和故障诊断等内容。

一、GraalVM介绍

GraalVM是由Oracle官方推出的一款高性能Java开发工具包(JDK),与OpenJDK和Oracle JDK相比,它为用户提供了更出色的性能。GraalVM标语为“Build faster, smaller, leaner applications”(更快、更小、更精简的应用程序开发)。GraalVM具有以下特点:

  • 低CPU和内存使用率:与传统的JDK相比,GraalVM在执行应用程序时可以显著降低CPU和内存的使用率,从而提高应用程序的性能。

image.gif

  • 快速启动和预热:GraalVM能够实现快速的应用程序启动,并且无需预热即可获得最佳性能,从而缩短了应用程序的启动时间。

image.gif

  • 更好的安全性:GraalVM提供了更高级别的安全性,可以更好地保护应用程序免受攻击和数据泄露等安全威胁。
  • 小型可执行文件:通过优化和压缩技术,GraalVM可以生成更小的可执行文件,从而减少了应用程序的存储空间占用。
  • 支持多种框架:GraalVM支持多种流行的Java框架,如Spring Boot、Micronaut、Helidon和Quarkus,使得开发人员可以更加方便地构建和部署应用程序。
  • 云平台支持:GraalVM已经得到了多家云平台的支持,使得开发人员可以轻松地将应用程序部署到云环境中。
  • 多语言支持:通过Truffle框架,GraalVM可以运行JavaScript、Python、Ruby等多种其他语言,从而扩展了其应用范围。


GraalVM的官方网址:https://www.graalvm.org/


GraalVM分为社区版(Community Edition)和企业版(Enterprise Edition)。与社区版相比,企业版在性能方面进行了更多的优化和改进,提供了更高级别的功能和特性。建议在开发高性能、安全可靠的应用程序时使用企业版GraalVM。

特性 描述 社区版 企业版
收费 是否收费 免费 收费
G1垃圾回收器 使用G1垃圾回收器优化垃圾回收性能 ×
Profile Guided Optimization(PGO) 运行过程中收集动态数据,进一步优化本地镜像的性能 ×
高级优化特性 更多优化技术,降低内存和垃圾回收的开销 ×
高级优化参数 更多的高级优化参数可以设置 ×

二、GraalVM的两种运行模式

JIT(Just-In-Time)模式(即时编译模式)

JIT模式是GraalVM的一种核心特性,其处理方式与Oracle JDK的JIT编译器类似。在这种模式下,GraalVM的即时编译器将Java字节码转换为本地机器码,以实现更高的执行效率。其主要特点如下:

  • 一次编写,到处运行(Write Once, Run Anywhere):这是Java的核心承诺,意味着开发者可以使用GraalVM在任何支持Java的平台或环境中编译和运行他们的代码。
  • 热点代码优化:预热之后,GraalVM的即时编译器会针对频繁执行的代码段进行优化,生成比传统的Hotspot JIT更高的性能机器码。

image.gif

AOT(Ahead-Of-Time)模式(提前编译模式)

AOT模式是GraalVM的另一项创新,它允许开发人员在编译阶段就生成特定平台的可执行文件。这意味着应用程序在启动时已经预先编译为本地代码,从而实现了更高的启动速度和运行性能。其主要特点如下:

  • 本地可执行文件生成:通过AOT编译器,开发人员可以为特定平台(如Windows、Linux或macOS)生成可执行文件(如.exe、.app或.out)。
  • 启动后达到最高性能:由于应用程序在启动时已经转换为本地代码,因此无需进行额外的编译或优化,可以立即达到最佳性能。
  • 非跨平台编译:与JIT模式不同,AOT模式下生成的可执行文件不具备跨平台特性。每个目标平台都需要单独编译。
  • 本地镜像(Native Image):AOT模式下生成的文件被称为本地镜像,它们是为特定平台和配置预先编译的应用程序映像。

image.gif

在选择使用GraalVM的哪种模式时,开发人员应考虑他们的应用程序需求、目标平台以及对性能、跨平台兼容性和安全性的要求。JIT模式提供了高度的跨平台兼容性和动态优化能力,而AOT模式则专注于预先编译的高性能和特定平台的可执行文件。

GraalVM模式和版本的性能对比:

image.gif

三、GraalVM应用场景

1.GraalVM存在的问题

GraalVM的AOT模式虽然带来了启动速度、内存和CPU开销上的优势,但也存在一些问题需要解决:

  • 跨平台问题:由于AOT模式下的代码是针对特定平台编译的,因此在使用不同平台运行时需要进行多次编译。这增加了开发人员的工作量,并需要确保编译平台的依赖库等环境与运行平台保持一致。
  • 编译时间与资源消耗:使用AOT模式编译本地镜像时,需要较长时间,并且会消耗大量的CPU和内存资源。这可能对开发环境和持续集成/持续部署(CI/CD)流程造成影响。
  • 运行时类访问限制:AOT编译器在编译时需要知道运行时所有可访问的类。然而,Java中存在一些技术可以在运行时动态创建类,例如反射、动态代理等。这些技术在许多框架中广泛使用,如Spring框架。因此,这些框架需要与AOT编译器进行适配,以确保其功能的正常使用。

针对上述问题,以下是一些可能的解决方案:

  • 使用容器化平台:利用公有云的Docker等容器化平台进行在线编译,可以确保编译环境和运行环境的一致性。这样不仅解决了跨平台问题,还解决了编译资源问题。通过容器化技术,可以轻松地在不同的环境中构建和部署应用程序。
  • 采用整合了GraalVM AOT模式的框架版本:例如,使用Spring Boot 3等框架版本,这些框架已经与GraalVM AOT模式进行了深度整合,简化了适配过程,并可能提供了更好的性能和功能支持。

2.GraalVM企业级应用-Serverless架构

在传统的系统架构中,企业需要自行负责服务器等基础设施的运维、安全和高可用性等方面的工作,这带来了两个主要问题:

  • 开销巨大:这包括了人力成本的开销和机房建设的开销。企业需要配备专门的技术团队进行基础设施的管理和维护,同时还需要投入大量的资源进行机房建设和设备采购。
  • 资源浪费:面对流量冲击,例如秒杀等促销活动,企业必须提前规划并准备大量的服务器资源。然而,在活动结束后,这些服务器可能会处于闲置状态,导致资源的严重浪费。

为了解决这些问题,随着虚拟化技术和云原生技术的不断成熟,云服务商开始提供Serverless无服务器化的架构。这种架构使得企业无需进行服务器的任何配置和部署,完全由云服务商负责提供和管理基础设施。Serverless架构能够根据应用程序的实际需求动态地分配资源,确保应用程序的高可用性和弹性扩展。

在Serverless架构中,企业可以将应用程序部署到云服务商提供的平台上,并利用云服务商提供的API和事件驱动的机制来编写业务逻辑。这样,企业可以专注于应用程序的开发和业务逻辑的实现,而无需关心基础设施的管理和维护。比较典型的Serverless服务提供商包括亚马逊AWS和阿里云等。这些云服务商提供了丰富的Serverless服务,如函数计算、数据库、存储和消息队列等,使得企业可以更加便捷地构建和部署Serverless应用程序。通过采用Serverless架构,企业可以降低开销、减少资源浪费,并实现应用程序的高可用性和弹性扩展。同时,与GraalVM的结合使用可以进一步提高应用程序的性能和安全性,为企业提供更加高效和可靠的解决方案。

3.Serverless架构-函数计算

在Serverless架构中,函数计算是一种常见的服务模式,它将应用程序拆分为多个独立的函数,每个函数都以事件驱动的方式运行。这种模式的核心思想是将应用程序的逻辑分解为一系列独立的、可复用的函数,从而提高了应用程序的可维护性和可扩展性。函数计算的服务提供商包括亚马逊AWS的Lambda和阿里云的FC等。这些服务提供商提供了全面的函数计算解决方案,使开发人员能够专注于编写和部署函数逻辑,而无需关心底层基础设施的管理和维护。

函数计算的主要应用场景包括:

  • 小程序和API服务中的接口:对于调用频率较低的接口,使用常规的服务器架构可能会导致资源浪费。通过使用Serverless架构,开发人员可以实现按需付费,降低成本,同时利用自动伸缩功能应对流量的突发情况。
  • 大规模任务处理:对于需要处理大量数据或执行复杂计算的任务,例如音视频文件转码、审核等,可以利用事件机制在文件上传后自动触发相应的任务。函数计算可以提供高效的资源利用和弹性扩展能力,以满足大规模任务处理的需求。

在计费方面,函数计算通常基于CPU和内存使用量进行计费。因此,使用GraalVM AOT模式编译本地镜像可以进一步降低成本。通过使用GraalVM AOT编译器,开发人员可以生成高效的本地镜像,从而减少运行函数所需的CPU和内存资源,进而降低函数计算的计费成本。

4.Serverless架构-Serverless应用

在Serverless架构中,除了函数计算服务外,云服务商还提供了基于容器的Serverless应用作为另一种解决方案。这种方案针对函数计算服务的局限性,为需要更长时间运行或更大资源需求的应用程序提供了支持。

基于容器的Serverless应用的核心优势在于其自动化的容器管理。与传统的手动配置Kubernetes中的Pod和Service等内容不同,基于容器的Serverless应用简化了这一过程。开发人员只需选择所需的镜像,云服务商即可自动生成应用服务,无需进行繁琐的配置和管理。这种方案适用于各种应用场景,特别是需要长时间运行或大量资源支持的应用。例如,一些批处理任务、大数据处理和分析、实时流数据处理等场景,都可以通过基于容器的Serverless应用实现高效的处理和扩展。

在计费方面,基于容器的Serverless应用通常也基于CPU和内存使用量进行计费。因此,使用GraalVM AOT模式编译本地镜像可以进一步降低成本。通过使用GraalVM AOT编译器,开发人员可以生成高效的本地镜像,从而减少运行应用所需的CPU和内存资源,进而降低基于容器的Serverless应用的计费成本。

四、参数优化和故障诊断

在GraalVM中,由于它是一款独立的JDK,许多在HotSpot虚拟机中常用的参数在这里并不适用。为了确保最佳的性能和稳定性,需要对GraalVM的参数进行细致的调整和优化。以下是一些关键的参数和故障诊断建议:

内存管理参数:

  • 最大堆大小(Max Heap Size): 社区版GraalVM默认使用串行垃圾回收器(Serial GC),其最大Java堆大小默认设置为物理内存的80%。如需调整,可以使用-Xmx参数来设置最大堆大小。如果希望在编译期就指定该大小,可以在编译时添加-R:MaxHeapSize=最大堆大小参数。
  • G1垃圾回收器: 企业版GraalVM提供了G1垃圾回收器,它能有效降低垃圾回收的延迟。开启方式为添加--gc=G1参数。
  • Epsilon GC: 对于生命周期短暂且不产生大量对象的程序,可以考虑使用Epsilon GC。它不会产生任何垃圾回收行为,从而没有额外的内存和CPU开销。开启方式为添加--gc=epsilon参数。

垃圾回收日志与诊断:

  • 使用-XX:+PrintGC-XX:+VerboseGC参数可以打印出垃圾回收的详细信息,这对于故障诊断和性能调优非常有帮助。

性能优化时可以指定的一小部分选项:

-H:G1HeapRegionSize(只能在映像构建时指定) - G1 区域的大小。
-XX:MaxRAMPercentage- 如果未另行指定最大堆大小,则用作最大堆大小的物理内存大小的百分比。
-XX:MaxGCPauseMillis- 最长暂停时间的目标。
-XX:ParallelGCThreads- 在垃圾回收暂停期间用于并行工作的最大线程数。
-XX:ConcGCThreads- 用于并发工作的最大线程数。
-XX:InitiatingHeapOccupancyPercent- 触发标记周期的 Java 堆占用阈值。
-XX:G1HeapWastePercent- 候选集合集中允许的未回收空间。如果候选收集组中的可用空间低于该值,则 G1 将停止空间回收阶段。

image.gif

其他常用的参数参考:

https://www.graalvm.org/22.3/reference-manual/native-image/optimizations-and-performance/MemoryManagement/


总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了GraalVM、GraalVM的两种运行模式、GraalVM应用场景、参数优化和故障诊断等内容,希望对大家有所帮助。

相关文章
|
3月前
|
Java Docker 索引
记录一次索引未建立、继而引发一系列的问题、包含索引创建失败、虚拟机中JVM虚拟机内存满的情况
这篇文章记录了作者在分布式微服务项目中遇到的一系列问题,起因是商品服务检索接口测试失败,原因是Elasticsearch索引未找到。文章详细描述了解决过程中遇到的几个关键问题:分词器的安装、Elasticsearch内存溢出的处理,以及最终成功创建`gulimall_product`索引的步骤。作者还分享了使用Postman测试接口的经历,并强调了问题解决过程中遇到的挑战和所花费的时间。
|
29天前
|
Java
jvm复习,深入理解java虚拟机一:运行时数据区域
这篇文章深入探讨了Java虚拟机的运行时数据区域,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、元空间和运行时常量池,并讨论了它们的作用、特点以及与垃圾回收的关系。
60 19
jvm复习,深入理解java虚拟机一:运行时数据区域
|
18天前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
9天前
|
存储 Dart Java
Dart 虚拟机运行原理
【10月更文挑战第20天】Dart 虚拟机通过一系列复杂的机制和操作,确保 Dart 代码能够准确、高效地执行。它为 Dart 语言的广泛应用提供了坚实的基础和可靠的运行环境
17 6
|
9天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
19天前
|
存储 算法 Java
深入理解Java虚拟机(JVM)及其优化策略
【10月更文挑战第10天】深入理解Java虚拟机(JVM)及其优化策略
33 1
|
29天前
|
前端开发 Java 应用服务中间件
JVM进阶调优系列(1)类加载器原理一文讲透
本文详细介绍了JVM类加载机制。首先解释了类加载器的概念及其工作原理,接着阐述了四种类型的类加载器:启动类加载器、扩展类加载器、应用类加载器及用户自定义类加载器。文中重点讲解了双亲委派机制,包括其优点和缺点,并探讨了打破这一机制的方法。最后,通过Tomcat的实际应用示例,展示了如何通过自定义类加载器打破双亲委派机制,实现应用间的隔离。
|
3月前
|
监控 算法 Java
深入理解Java虚拟机:JVM调优与性能提升
本文旨在为Java开发者提供一条清晰的路径,以深入掌握Java虚拟机(JVM)的内部机制和性能调优技巧。通过具体案例分析,我们将探讨如何识别性能瓶颈、选择合适的工具进行监控与调试,以及实施有效的优化策略,最终达到提高应用程序性能的目的。文章不仅关注理论,更注重实践应用,帮助读者在面对复杂的Java应用时能够游刃有余。
69 0
|
20天前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
32 4
|
20天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
44 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS