性能调优 17. GraalVM云原生时代的Java虚拟机

1. GraalVM诞生的背景

1.1. Java在微服务/云原生时代的困境及解决方案

‌‌‌  事实

‌‌‌  Java总体上是面向大规模、长时间的服务端应用而设计的。
‌‌‌  即时编译器(JIT)、性能优化、垃圾回收等有代表性的特征需要一段时间来达到最佳性能

‌‌‌  矛盾

‌‌‌  微服务时代对启动速度达到最高性能的时间提出了新的要求!

‌‌‌  在微服务的背景下,提倡服务围绕业务能力构建,不再追求实现上的严谨一致。

‌‌‌  单个微服务就不再需要再面对数十、数百GB乃至TB的内存。

‌‌‌  有了高可用的服务集群,也无须追求单个服务要7×24小时不可间断地运行,它们随时可以中断和更新。

‌‌‌  所以微服务对应用的容器化(Docker)亲和度(包容量、内存消耗等)、启动速度、达到最高性能的时间等方面提出了新的要求,这些恰恰是Java的弱项。

‌‌‌  比如:现在启动一个微服务项目(Docker运行6个子服务),动不动就1分钟,如下图:

在这里插入图片描述

‌‌‌  问题根源

‌‌‌  Java离不开虚拟机。

‌‌‌  所以Java应用启动的时候,必须要启动虚拟机,进行类加载,无论是启动时间,还是占用空间都不是最优解。

‌‌‌  解决方案

‌‌‌  革命派

‌‌‌  直接革掉Java和Java生态的性命,创造新世界,譬如Golang。

‌‌‌  保守派

‌‌‌  保留原有主流Java生态和技术资产,朝着微服务、云原生环境靠拢与适应(GraaIVM)。

2. GraalVM入门

‌‌‌  GraalVM 是一个高性能 JDK 发行版,旨在加速用Java和其它JVM语言编写的应用程序的执行(JVM不只支持Java语言)并支持 JavaScript、Ruby、Python 和许多其他流行语言(翻译自官网 https://www.graalvm.org/)。

‌‌‌  GraalVM底层也是HosSpot,只是做了二次开发,打包成JDK。GraalVM能让支持的语言使用HotSpot虚拟机

‌‌‌  GraalVM可以代替对应的JDK版本使用。

在这里插入图片描述

‌‌‌  GraalVM想成为一统天下的“最终”虚拟机!而GraalVM要做到原因也很简单:

‌‌‌  大部分脚本语言或者有动态特效的语言都需要一个语言虚拟机运行,比如CPython,Lua,Erlang,Java,Ruby,R,JS,PHP,Perl,APL等等,但是这些语言的虚拟机水平很烂,比如CPython的VM就不忍直视,而HotSpotVM是虚拟机的大神级别,如果能用上HotSpot,能用上顶级的即时编译器(JIT)、性能优化、垃圾回收等技术,岂不爽歪歪!

3. GraalVM特征

‌‌‌  1. GraalVM是一款高性能的可嵌入式多语言虚拟机,它能运行不同的编程语言

‌‌‌  能运行基于JVM的语言,比如Java, Scala, Kotlin和Groovy。

‌‌‌  能运行解释型语言,比如JavaScript, Ruby, R和Python。

‌‌‌  能运行,能配合LLVM运行的原生语言,比如C, C++, Rust和Swift。

‌‌‌  2. GraalVM的设计目标是可以在不同的环境中运行程序在JVM中。

‌‌‌  将代码编译成独立的本地镜像(不需要JVM),比如将Java代码编译成本地镜像就可以直接运行,不需要安装JDK环境。(符合云原生的要求不需要在环境里头再安装JDK)

‌‌‌  将Java及本地代码模块集成为更大型的应用。

4. 安装配置GraalVM

‌‌‌  下载压缩包

‌‌‌  GraalVM分成了社区版与企业版,企业版肯定比社区版好,企业版可能涉及到收费问题。

在这里插入图片描述

‌‌‌  这边因为演示使用社区版就够了,按JDK版本下载GraalVM对应的压缩包,请下载Java 17对应的版本,不然后面实战演示SpringBoot3(需要JDK17)可能会有问题。
‌‌‌  
‌‌‌  下载地址 https://github.com/graalvm/graalvm-ce-builds/releases

在这里插入图片描述

‌‌‌‌‌‌  ‌‌‌下载完后,解压。
在这里插入图片描述

‌‌‌‌‌‌  配置环境变量

类似这样
在这里插入图片描述

‌‌‌  新开一个cmd测试,不同版本显示不一样。
在这里插入图片描述

‌‌‌  安装native-image

‌‌‌  cmd下运行gu list,查看有没安装native-image。

在这里插入图片描述

1. 在线安装

‌‌‌  执行gu install native-image 命令安装即可。

‌‌‌  2. 离线安装

‌‌‌  以 GraalVM for JDK 17 Community 17.0.8 对应的23.0.1 版本为例, 地址:

‌‌‌  下载地址:https://github.com/graalvm/graalvm-ce-builds/releases/tag/graal-23.0.1。

‌‌‌  找到 native-image-installable-svm-java17-windows-amd64-23.0.1.jar 下载。

在这里插入图片描述

‌‌‌  打开cmd, 进入 native-image-installable-svm-java17-windows-amd64-23.0.1.jar 下载的文件夹。

在这里插入图片描述

执行:gu install -L native-image-installable-svm-java17-windows-amd64-23.0.1.jar 安装即可。

‌‌‌  验证运行gu list查看是否安装成功。

注意

‌‌‌  1. 如graalvm 和native-image 版本不一致,会出现如下图的错误,找到对应的版本,重新安装即可;

在这里插入图片描述

‌‌‌  安装Visual Studio Build Tools

‌‌‌  因为在Windows上 使用要使用GraalVM的native-image打包需要c++环境,而VisualStudio 可以提供c++开发环境,所以我们要先下载安装好VisualStudio。

‌‌‌  打开 visualstudio.microsoft.com这个网站 ,下载Visual Studio Installer。

‌‌‌  选择C++桌面开发和Windows 11 SDK,然后进行下载和安装,安装后重启操作系统。

在这里插入图片描述
  要使用GraalVM的native-image将代码编译成本地文件,不能使用普通的windows自带的命令行窗口。得使用VS提供的 x64 Native Tools Command Prompt for VS版本号
‌‌‌  如下

在这里插入图片描述

‌‌‌  如果没有可以执行前面Visual Studio Build Tools安装目录文件夹下的Microsoft Visual Studio\版本号\BuildTools\VC\Auxiliary\Build\vcvars64.bat**脚本来安装。

‌‌‌  安装完之后可以运行x64 Native Tools Command Prompt for VS 版本号 ,去使用native-image命令去进行编译代码生成本地文件了。

在这里插入图片描述

‌‌‌  如果后续在编译过程中编译失败了,出现以下错误:

在这里插入图片描述
‌‌‌  那么可以执行cl.exe来进行编译,cl.exe如果是中文,那就得修改为英文。

在这里插入图片描述
‌‌‌  可以通过再次启用Visual Studio Installer来修改你的安装配置,比如:

在这里插入图片描述

在这里插入图片描述

‌‌‌  可能一开始只选择了中文,手动选择英文,去掉中文,然后安装(修改)即可。

‌‌‌  再次检查,这样就可以正常的编译了。

在这里插入图片描述

5. Graal Compiler(了解就好)

‌‌‌  Graal Compiler是GraalVM与HotSpotVM(从JDK10起)共同拥有的服务端即时编译器,是C2编译器的替代者

‌‌‌  Graal VM结构图如下

‌‌‌‌‌‌  Graal Java–就是Graal编译器。

‌‌‌  JVMCI—针对JVM编译的接口,因为Graal编译器是java写的,通过Compiler Interface调用JVM很麻烦就使用这个替代。

在这里插入图片描述

‌‌‌  即时编译器(JIT编译器)是 Java 虚拟机中相对独立的模块,它主要负责接收 Java 字节码,并生成可以直接运行的二进制码。传统情况下(JDK8),即时编译器是与 Java 虚拟机紧耦合的。也就是说,对即时编译器的更改需要重新编译整个 Java 虚拟机。这对于开发相对活跃的 Graal 来说显然是不可接受的。

‌‌‌  为了让 Java 虚拟机与 Graal编译器解耦合,引入了Java 虚拟机编译器接口(JVM Compiler Interface,JVMCI),因为Graal编译器是java编写的,将即时编译器的功能抽象成一个 Java 层面的接口。这样一来,在 Graal 所依赖的 JVMCI 版本不变的情况下,我们仅需要替换 Graal 编译器相关的 jar 包(Java 9 以后的 jmod 文件),便可完成对 Graal 的升级。

6. C2编译器的Bug

‌‌‌  C2还存在一些小BUG

‌‌‌  例如

‌‌‌  package enjoy.jvm.jit;
‌‌‌  /*** @author  King老师* C2的BUG* -Xint  参数强制虚拟机运行于只有解释器的编译模式*/
‌‌‌  public class C2Bug {public void test() {int i = 8;while ((i -= 3) > 0);System. out .println("i = " + i);}public static void main(String[] args) {C2Bug c2bug = new C2Bug();for (int i = 0; i < 50_000; i++) {//5万次   前1万次  不会触发JIT及时编译(没有性能优化)、后4万次JITc2bug.test();}}
‌‌‌  }

在这里插入图片描述

‌‌‌  使用-Xint参数强制虚拟机运行于只有解释器的编译模式,就不会出现问题。

在这里插入图片描述

‌‌‌  另外把循环次数降低,降低到5000次,就不会触发JIT,就不会触发C2的优化也不会出现问题。

在这里插入图片描述

在这里插入图片描述

‌‌‌  把JDK改成GraalVM,则触发热点探测会使用GraalVM的即时编译器器进行编译优化,也能避免上述Bug

7. Graal 即时编译器和C2即时编译器区别

‌‌‌  Graal 和 C2 最为明显的一个区别是:Graal 是用 Java 写的,而 C2 是用 C++ 写的

‌‌‌  相对来说,Graal 更加模块化,也更容易开发与维护,毕竟,连C2的开发者都不想去维护C2了。

‌‌‌  许多人会觉得用 C++ 写的 C2 肯定要比 Graal 快。实际上,在充分预热的情况下,Java 程序中的热点代码早已经通过即时编译转换为二进制码,在执行速度上并不亚于静态编译的 C++ 程序

‌‌‌  Graal 的内联算法对新语法、新语言更加友好,例如 Java 8 的 lambda 表达式以及 Scala 语言。

‌‌‌  对比例子


‌‌‌  package enjoy.jvm.jit;‌‌‌  public class JavaCountUppercase {static final int ITERATIONS = Math.max(Integer.getInteger("iterations", 1), 1);public static void main(String[] args) {String sentence = String.join(" ", args);for (int iter = 0; iter < ITERATIONS; iter++) {if (ITERATIONS != 1) System.out.println("-- iteration " + (iter + 1) + " --");long total = 0, start = System.currentTimeMillis(), last = start;for (int i = 1; i < 100_000_000; i++) {total += sentence.chars().filter(Character::isUpperCase).count();if (i % 10_000_000 == 0) {long now = System.currentTimeMillis();System.out.printf("%d (%d ms)%n", i / 10_000_000, now - last);last = now;}}System.out.printf("total: %d (%d ms)%n", total, System.currentTimeMillis() - start);}}
‌‌‌  }

‌‌‌  使用原生JDK8触发热点探测,使用C2编译器进行即时编译结果如下。

在这里插入图片描述

‌‌‌  JDK换成GraalVM运行结果如下。
 
在这里插入图片描述

8. GraalVM的AOT技术和实战

8.1. Graal的AOT技术

Graal 的Aot 属于GraalVM 中的一项技术,说白就是Ahead-of-time compile(提前编译),在编译期时,会把需要编译的东西,包含一个基底的 VM,一起编译成机器码(二进制)。代码直接编译成机器码后可直接运行,类似C++编译代码一样。

‌‌‌  Spring6.0开始也引入了自己的AOT技术,也就是Spring Boot3.0借助AOT技术在GraalVM环境下可以将项目打包成本地文件直接执行。

‌‌‌  GraalVM在编译成二进制可执行文件时,GraalVM不会把代码都编译成到二进制文件中。需要确定该应用到底用到了哪些类、其中用到了哪些方法、哪些属性,从而把这些用到的代码编译为机器指令(也就是exe文件)

‌‌‌  比如我们一个应用中某些类可能是动态生成的,也就是应用运行后才生成的,为了解决这个问题,GraalVM提供了配置的方式,可以让我们在编译时告诉GraalVM哪些类是动态生成类需要用到,可以通过proxy-config.json、reflect-config.json来进行配置

‌‌‌  比如在reflect-config.json这样配置告诉GraalVM,代码反射中使用到类有哪些,反射使用的构造方法是什么,该类反射创建对象后会使用反射方法是什么。
在这里插入图片描述
  Spring Boot3.0可以通过Runtime Hints机制来配置GraalVM的配置文件,也就是通过类方式配置这些信息,GraalVM打包Spring Boot3.0项目成本地文件过程中,会根据这些类写配置信息到GraalVM的配置文件中(这个机制怎么配,这边不说了知道就好)。

8.2. Graal的AOT技术的优缺点

‌‌‌  缺点

‌‌‌  1. 没法动态生成机器码,不像JAVA可以动态生成类。GraalVM在编译成二进制可执行文件时,需要确定该应用到底用到了哪些类、哪些方法、哪些属性,从而把这些代码编译为机器指令(也就是exe文件)。但是我们一个应用中某些类可能是动态生成的,也就是应用运行后才生成的,为了解决这个问题,GraalVM提供了配置的方式,可以让我们在编译时告诉GraalVM哪些类会动态生成类,比如我们可以通过proxy-config.json、reflect-config.json来进行配置

‌‌‌  2. 编译慢。

‌‌‌  优点

‌‌‌  1. 项目编译后的文件,是能直接执行的文件,启动和执行速度都很快,只依赖操作系统。

‌‌‌  2. 编译时候考虑编译出的文件太大,GraalVM不会把用到的类都编译成到二进制文件中,而是会把用到的代码编译到二进制文件中。

8.3. 实战例子

8.3.1. Hello World实战

‌‌‌  新建一个简单的Java工程:

在这里插入图片描述

‌‌‌  我们可以直接把graalvm当作普通的jdk的使用
在这里插入图片描述

在这里插入图片描述

‌‌‌  打开x64 Native Tools Command Prompt for VS 版本号,进入工程目录下,并利用javac将java文件编译为class文件:javac -d . src/com/zhouyu/App.java

‌‌‌  -d. 这个命令意思根据当前目录找指定的相对路径下的App.java文件进行编译,然后编译后输出的目录是相对路径。根据App.java的package指定的目录。比如我App.java的packge改成com,那么就会输出到当前目录(src目录下)com文件夹下。

在这里插入图片描述

‌‌‌  此时的class文件因为有main方法,所以用java命令可以运行。
在这里插入图片描述

‌‌‌  利用native-image来编译生成的字节码文件,转成exe文件。

在这里插入图片描述

‌‌‌  注意

‌‌‌  1. 为啥指定class文件要使用com.zhouyu.App,因为App的package是com.zhouyu。上面命令代码意思是会以当前所在目录为基础,去运行com/zhouyu下的App的class文件。

‌‌‌  然后按照class文件的package指定的包路径做为相对路径转化为文件路径去搜索class文件。

‌‌‌  2. 可以使用-o参数来指定exe文件的名字:


‌‌‌  native-image com.zhouyu.App -o app

‌‌‌  编译需要一些时间。
在这里插入图片描述
‌‌‌  编译完了之后就会在当前目录生成一个exe文件:

在这里插入图片描述
‌‌‌  可以直接运行这个exe文件

在这里插入图片描述
‌‌‌  并且运行这个exe文件是不需要操作系统上安装了JDK环境的

8.3.2. GraalVM下的SpringBoot 3.0实战

‌‌‌
‌‌‌  新建一个Maven工程,添加SpringBoot3.0相关依赖,就是一个SpringBoot 3.0项目了。


‌‌‌  <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.0.0</version>
‌‌‌  </parent>‌‌‌  <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
‌‌‌  </dependencies>

‌‌‌  配置变量

<properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.build-image.imageName>自己项目名字</spring-boot.build-image.imageName></properties>

‌‌‌  要编译成exe需要下面这些插件。这些插件跟Spring AOT有关,同时借助这些插件一键打包项目生成执行本地文件。


‌‌‌  <build><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><version>0.9.28</version></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
‌‌‌  </build>

‌‌‌  创建一些代码

‌‌‌  @RestController
‌‌‌  public class ZhouyuController {@Autowiredprivate UserService userService;@GetMapping("/demo")public String test() {return userService.test();}‌‌‌  }
‌‌‌  package com.zhouyu;‌‌‌  import org.springframework.stereotype.Component;‌‌‌  @Component
‌‌‌  public class UserService {public String test(){return "hello zhouyu";}
‌‌‌  }

‌‌‌  package com.zhouyu;‌‌‌  import org.springframework.boot.SpringApplication;
‌‌‌  import org.springframework.boot.autoconfigure.SpringBootApplication;‌‌‌  @SpringBootApplication
‌‌‌  public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
‌‌‌  }

‌‌‌  这本身就是一个普通的SpringBoot工程,可以使用之前的方式打成jar包运行。

‌‌‌  同时也支持用native-image命令把整个SpringBoot工程编译成为一个exe文件执行。在 x64 Native Tools Command Prompt for VS 版本号中,进入到工程目录下,执行mvn -Pnative native:compile(如果报mvn不存在,注意配置下maven的路径到环境变量)进行编译就可以了,这命令包含项目编译成class过程,不需要再编译项目成字节码再去编,就能在项目的target目录下生成对应的exe文件,后续只要运行exe文件就能启动应用了。

‌‌‌  在执行命令之前,请确保环境变量中设置了Graal VM 的路径,因为过程需要用到Graal VM 编译成本地文件

‌‌‌  编译完成截图:
‌‌‌  ‌‌‌如果编译过程中日志没有滚动回车下。

在这里插入图片描述
在这里插入图片描述
‌‌‌  直接运行jar包和直接运行exe启动速度区别

在这里插入图片描述
  注意

‌‌‌  1. 项目存放目录不要有中文,不然打包编译会报错。

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

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

相关文章

4、Python+MySQL+Flask的文件管理系统【附源码,运行简单】

4、PythonMySQLFlask的文件管理系统【附源码&#xff0c;运行简单】 总览 1、《文件管理系统》1.1 方案设计说明书设计目标工具列表 2、详细设计2.1 登录2.2 注册2.3 个人中心界面2.4 文件上传界面2.5 其他功能贴图 3、下载 总览 自己做的项目&#xff0c;禁止转载&#xff0c…

大厂面试官问我:两个1亿行的文件怎么求交集?【后端八股文十五:场景题合集】

本文为【场景题合集】初版&#xff0c;后续还会进行优化更新&#xff0c;欢迎大家关注交流~ hello hello~ &#xff0c;这里是绝命Coding——老白~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f…

Unity UGUI 之 Input Field

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 1.Input Field是什么&#xff1f; 给玩家提供输入的输入框 2.重要参数 中英文对照着看…

设计模式|观察者模式

观察者模式是一种行为设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。当主题对象发生变化时&#xff0c;它的所有观察者都会收到通知并更新。观察者模式常用于实现事件处理系统、发布-订阅模式等。在项目中&#xff0c…

爬虫学习4:爬取王者荣耀技能信息

爬虫&#xff1a;爬取王者荣耀技能信息&#xff08;代码和代码流程&#xff09; 代码 # 王者荣耀英雄信息获取 import time from selenium import webdriver from selenium.webdriver.common.by import By if __name__ __main__:fp open("./honorKing.txt", "…

nginx隐藏server及版本号

1、背景 为了提高nginx服务器的安全性&#xff0c;降低被攻击的风险&#xff0c;需要隐藏nginx的server和版本号。 2、隐藏nginx版本号 在 http {—}里加上 server_tokens off; 如&#xff1a; http {……省略sendfile on;tcp_nopush on;keepalive_timeout 60;tcp_nodelay o…

Microsoft 365 Office BusinessPro LTSC 2024 for Mac( 微软Office办公套件)

Microsoft 365 Office BusinessPro LTSC 2024是一款专为商业用户设计的办公软件套件&#xff0c;它集成了Word、Excel、PowerPoint等核心应用&#xff0c;并特别包含了Microsoft Teams这一强大的协作工具。Teams将聊天、会议、文件共享、任务管理等功能整合到一个平台上&#x…

【黑科技】:Laravel 项目性能提升 20 倍

令人激动的黑科技&#xff1a;Laravel 项目性能提升 20 倍 这个项目能够在无需修改任何代码且无需第三方扩展的前提下&#xff0c;将你的 Laravel 项目性能提高 20 倍。它仅依赖于 PHP 原生的 pcntl、posix、fiber 和 sockets。 项目灵感 起因是看到官方发布的 PHP 8.1 更新…

软件开发者消除edge浏览器下载时“此应用不安全”的拦截方法

当Microsoft Edge浏览器显示“此应用不安全”或者“已阻止此不安全的下载”这类警告时&#xff0c;通常是因为Windows Defender SmartScreen或者其他安全功能认为下载的文件可能存在安全风险。对于软件开发者来说&#xff0c;大概率是由于软件没有进行数字签名&#xff0c;导致…

河南萌新联赛2024第(二)场:南阳理工学院

文章目录 原题链接A.国际旅行Ⅰ题意&#xff1a;思路&#xff1a;代码&#xff1a; F.水灵灵的学弟题意&#xff1a;思路&#xff1a;代码 I.重生之zbk要拿回属于他的一切题意&#xff1a;思路&#xff1a;代码&#xff1a; J.这是签到题意&#xff1a;思路&#xff1a;代码&am…

畅游时空|虚拟世界初体验,元宇宙游戏如何开发?

在元宇宙中&#xff0c;用户可以通过虚拟身份进行互动、社交、工作和娱乐&#xff0c;体验与现实世界平行的生活和活动。元宇宙不仅仅是一个虚拟空间&#xff0c;更是一个融合了虚拟和现实的生态系统&#xff0c;具有巨大的发展潜力和应用前景。 在不断发展的数字环境中&#x…

NCRE3 2-1 网络总体设计基本方法

这部分记忆的比较多 概览 设计网络建设总体目标确定网络系统方案设计原则网络系统总体设计设计网络拓扑结构进行网络设备选型网络系统安全设计 设计网络建设总体目标 这部分视频没说到 确定网络系统方案设计原则 这部分视频没说到 网络系统总体设计 核心层网络结构设计 …

图形编辑器基于Paper.js教程09:鼠标拖动画布,以鼠标点为缩放中心进行视图的缩放

如何使用Paper.js实现画布的缩放与拖动功能 在Web开发中&#xff0c;利用Paper.js库进行图形的绘制和交互操作是一种常见的实践。Paper.js是一个强大的矢量图形库&#xff0c;可以让开发者通过简洁的API完成复杂的图形操作。在本文中&#xff0c;我们将详细探讨如何使用Paper.…

Dify中接入GPT-4o mini模型

GPT-4o mini模型自己承认是基于GPT-3.5架构的模型&#xff0c;有图有真相&#xff1a; 一.GPT-4o mini官网简介 GPT-4o mini&#xff08;“o"代表"omni”&#xff09;是小型型号类别中最先进的型号&#xff0c;也是OpenAI迄今为止最便宜的型号。它是多模态的&#x…

idea一键为实体类赋值

file -> settings -> plugins -> marketplace 把这个插件装上 找个实体&#xff0c;选中&#xff0c;altenter进入edit界面 我是选择只保留右边这种生成方法&#xff0c;然后选择ok 返回到那个实体&#xff0c;选择&#xff0c;altenter generate生成

键盘是如何使用中断机制的?当打印一串字符到显示屏上时发生了什么???

当在键盘上按下一个键时会进行一下操作&#xff1a; 1.当按下任意一个键时&#xff0c;键盘编码器监控会来判断按下的键是哪个 2.键盘控制器用将解码,将键盘的数据保存到键盘控制器里数据寄存器里面 3.此时发送一个中断请求给中断控制器&#xff0c;中断控制器获取到中断号发送…

PyTorch基础(24)--torch.multinomial()方法

&#x1f449;torch.multinomial的源码见https://github.com/dongjinkun/PyTorch/tree/main/torch 一、前言 torch.multinomial()方法多出现在需要采样的场景中&#xff0c;如强化学习。具体讲&#xff0c;当使用强化学习解决旅行商问题时&#xff0c;针对某一个instance&…

Spring Boot集成Spring Batch快速入门Demo

1.什么是Spring Batch&#xff1f; Spring Batch 是一个轻量级的开源框架&#xff0c;它提供了一种简单的方式来处理大量的数据。它基于Spring框架&#xff0c;提供了一套批处理框架&#xff0c;可以处理各种类型的批处理任务&#xff0c;如ETL、数据导入/导出、报表生成等。S…

【通信协议-RTCM】MSM语句(2) - RINEXMSM7语句总结(重要!自动化开发计算卫星状态常用)

注释&#xff1a; 在工作中主要负责的是RTCM-MSM7语句相关开发工作&#xff0c;所以主要介绍的就是MSM7语句相关内容 1. 相位校准参考信号 2. MSM1、MSM2、MSM3、MSM4、MSM5、MSM6和MSM7的消息头内容 DATA FIELDDF NUMBERDATA TYPENO. OF BITSNOTES Message Number - 消息编…

基于STM32的农业大棚温湿度采集控制系统的设计

目录 1、设计要求 2、系统功能 3、演示视频和实物 4、系统设计框图 5、软件设计流程图 6、原理图 7、主程序 8、总结 &#x1f91e;大家好&#xff0c;这里是5132单片机毕设设计项目分享&#xff0c;今天给大家分享的是智能教室。 设备的详细功能见网盘中的文章《8、基…