探索Java的DNA-JVM字节码深度解析


引言

在Java的世界里,JVM(Java虚拟机)是我们程序运行的心脏。而字节码,作为JVM的血液,携带着程序的执行指令。今天,我们将深入探索Java字节码的奥秘,一窥JVM如何将人类可读的代码转化为机器可执行的指令。


一、JVM 知识回顾


JVM是一个可以执行Java字节码的虚拟计算机,它包括类加载器、运行时数据区、执行引擎等核心组件。JVM架构保证了Java程序的平台独立性,实现了“一次编写,到处运行”的理念。

关于Java虚拟机的工作原理、作用和应用场景, 感兴趣的朋友请前往查看:Java虚拟机揭秘-底层驱动力,性能保障!


二、Class文件结构


Class文件是JVM执行字节码的载体,它以8位字节为基础单位的二进制流形式存在。Class文件的结构包括魔数、版本号、常量池、字段表集合、方法表集合等。

在这里插入图片描述


下面以一个例子逐步讲解字节码。

//Test.java
public class Test {
    
    private int a;
    
    public int num() {
        return a + 1;
    }
}

通过执行以下命令, 可以在当前所在路径下生成一个Test.class文件。

javac Test.java

以文本形式打开Test.class文件,内容如下:

cafe babe 0000 003d 0013 0a00 0200 0307
0004 0c00 0500 0601 0010 6a61 7661 2f6c
616e 672f 4f62 6a65 6374 0100 063c 696e
6974 3e01 0003 2829 5609 0008 0009 0700
0a0c 000b 000c 0100 0454 6573 7401 0001
6101 0001 4901 0004 436f 6465 0100 0f4c
696e 654e 756d 6265 7254 6162 6c65 0100
036e 756d 0100 0328 2949 0100 0a53 6f75
7263 6546 696c 6501 0009 5465 7374 2e6a
6176 6100 2100 0800 0200 0000 0100 0200
0b00 0c00 0000 0200 0100 0500 0600 0100
0d00 0000 1d00 0100 0100 0000 052a b700
01b1 0000 0001 000e 0000 0006 0001 0000
0002 0001 000f 0010 0001 000d 0000 001f
0002 0001 0000 0007 2ab4 0007 0460 ac00
0000 0100 0e00 0000 0600 0100 0000 0700
0100 1100 0000 0200 12

  • 文件开头的4个字节(“cafe babe”)称之为 魔数,唯有以"cafe babe"开头的class文件方可被虚拟机所接受,这4个字节就是字节码文件的身份识别。

  • 0000是编译器jdk版本的次版本号0


三、反编译字节码文件


使用 javap 命令反编译 Java 字节码文件是一个查看 .class 文件内部结构和字节码指令的简单方法。

用法: javap <options> <classes>

其中<options>选项包括:

-help  --help  -?        输出此用法消息
  -version                 版本信息
  -v  -verbose             输出附加信息
  -l                       输出行号和本地变量表
  -public                  仅显示公共类和成员
  -protected               显示受保护的/公共类和成员
  -package                 显示程序包/受保护的/公共类
                           和成员 (默认)
  -p  -private             显示所有类和成员
  -c                       对代码进行反汇编
  -s                       输出内部类型签名
  -sysinfo                 显示正在处理的类的
                           系统信息 (路径, 大小, 日期, MD5 散列)
  -constants               显示最终常量
  -classpath <path>        指定查找用户类文件的位置
  -cp <path>               指定查找用户类文件的位置
  -bootclasspath <path>    覆盖引导类文件的位置

以下是如何使用 javap 命令的基本步骤:

  • 第一步,编译 Java 源文件: 首先,你需要有一个 .class 文件。如果你有一个 .java 源文件,可以使用 javac 命令将其编译成 .class 文件。例如:
javac Test.java

这将在当前目录下生成一个名为 Test.class 的字节码文件。

在这里插入图片描述


  • 第二步,使用 javap 命令: 打开命令行工具(在 Windows 上是 CMD 或 PowerShell,在 macOS 或 Linux 上是 Terminal),然后使用 javap 命令查看 .class 文件的内容。

    可以使用:

    javap -c Test
    

  • 第三步,查看输出: 执行 javap 命令后,你将看到 .class 文件的详细信息,包括类定义、字段、方法以及它们的字节码指令。

在这里插入图片描述

  • 第四步,输出到文件: 如果你想要将 javap 的输出保存到文件中,可以使用重定向操作符 >
javap -c Test > output.txt

这将把 Test.class 文件的字节码指令输出到 output.txt 文件中。

在这里插入图片描述


请注意,javap 主要用于查看字节码指令和类的结构,而不是将 .class 文件完全反编译回 Java 源代码。

如果你需要将 .class 文件反编译为更接近原始源代码的形式,可能需要使用其他专门的反编译工具。


四、字节码文件.class详细解读


执行以下命令,可查看子节码文件内容:

javap -verbose -p Test.class
  Last modified 2024年5月26日; size 265 bytes
  SHA-256 checksum aeba5b65f486bc4f6ee16ec2073e4fec2053987d53cdaed540343c6230966095
  Compiled from "Test.java"
public class Test
  minor version: 0
  major version: 61
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #8                          // Test
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 1, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Fieldref           #8.#9          // Test.a:I
   #8 = Class              #10            // Test
   #9 = NameAndType        #11:#12        // a:I
  #10 = Utf8               Test
  #11 = Utf8               a
  #12 = Utf8               I
  #13 = Utf8               Code
  #14 = Utf8               LineNumberTable
  #15 = Utf8               num
  #16 = Utf8               ()I
  #17 = Utf8               SourceFile
  #18 = Utf8               Test.java
{
  private int a;
    descriptor: I
    flags: (0x0002) ACC_PRIVATE

  public Test();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 2: 0

  public int num();
    descriptor: ()I
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: getfield      #7                  // Field a:I
         4: iconst_1
         5: iadd
         6: ireturn
      LineNumberTable:
        line 7: 0
}
SourceFile: "Test.java"

以上信息是使用 javap 命令反编译 Test.class 文件后得到的输出结果。它展示了 .class 文件的内部结构和相关信息。


下面是对输出结果的详细解析:

(1)、文件元信息

  • Last modified:文件最后修改时间。

  • size:文件大小。

  • SHA-256 checksum:文件的 SHA-256 校验和。


(2)、编译信息

  • Compiled from "Test.java":表明 Test.class 文件是由 Test.java 源文件编译而来。


(3)、类定义

  • public class Test:定义了一个名为 Test 的公共类。


(4)、版本信息

  • minor version: 0major version: 61:表示这个 .class 文件的 Java 版本信息,主版本号是 61,这对应于 Java 17。


(5)、访问标志

  • flags: (0x0021) ACC_PUBLIC, ACC_SUPER:类的标志,ACC_PUBLIC 表示这个类是公开的,ACC_SUPER 是一个默认标志,表示这个类不是 final 的。


    访问标志的含义如下:

    标志名称标志值含义
    ACC_PUBLIC0x0001是否为Public类型
    ACC_FINAL0x0010是否被声明为final,只有类可以设置
    ACC_SUPER0x0020是否允许使用invokespecial字节码指令的新语义.
    ACC_INTERFACE0x0200标志这是一个接口
    ACC_ABSTRACT0x0400是否为abstract类型,对于接口或者抽象类来说,次标志值为真,其他类型为假
    ACC_SYNTHETIC0x1000标志这个类并非由用户代码产生
    ACC_ANNOTATION0x2000标志这是一个注解
    ACC_ENUM0x4000标志这是一个枚举

(6)、常量池

Constant pool
  • 常量池可以理解成Class文件中的资源仓库,包含了类文件中的各种常量引用,例如方法引用、类名、字段名等。

  • 常量池主要存放的是两大类常量:字面量(Literal)和符号引用(Symbolic References)。

  • 字面量类似于java中的常量概念,如文本字符串,final常量等。

  • 符号引用则属于编译原理方面的概念,包括以下三种:

    • 类和接口的全限定名(Fully Qualified Name)

    • 字段的名称和描述符号(Descriptor)

    • 方法的名称和描述符

JVM是在加载Class文件的时候才进行的动态链接,也就是说这些字段和方法符号引用只有在运行期转换后才能获得真正的内存入口地址。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建或运行时解析并翻译到具体的内存地址中。

例如:

  • #1 = Methodref #2.#3:引用了 java/lang/Object 类的无参构造方法 <init>()V

  • #7 = Fieldref #8.#9:引用了 Test 类中的字段 a


(7)、字段

  • private int a;:定义了一个名为 a 的私有整型字段。

(8)、构造方法

  • public Test();:定义了一个公共的无参构造方法,用于实例化 Test 类的对象。

  • Code:构造方法的字节码指令,这里调用了父类 Object 的构造方法。


    Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: invokespecial #1                  // Method java/lang/Object."<init>":()V
             4: return
          LineNumberTable:
            line 2: 0
    

    code内的主要属性为:

    • stack: 最大操作数栈,JVM运行时会根据这个值来分配栈帧(Frame)中的操作栈深度,此处为1。

    • locals: 局部变量所需的存储空间,单位为Slot, Slot是虚拟机为局部变量分配内存时所使用的最小单位,为4个字节大小。方法参数(包括实例方法中的隐藏参数this),显示异常处理器的参数(try catch中的catch块所定义的异常),方法体中定义的局部变量都需要使用局部变量表来存放。值得一提的是,locals的大小并不一定等于所有局部变量所占的Slot之和,因为局部变量中的Slot是可以重用的。

    • args_size: 方法参数的个数,这里是1,因为每个实例方法都会有一个隐藏参数this.

    • LineNumberTable: 该属性的作用是描述源码行号与字节码行号(字节码偏移量)之间的对应关系。可以使用 -g:none 或-g:lines选项来取消或要求生成这项信息,如果选择不生成LineNumberTable,当程序运行异常时将无法获取到发生异常的源码行号,也无法按照源码的行数来调试程序。


(9)、方法

  • public int num();:定义了一个名为 num 的公共方法,返回类型为 int

  • Codenum 方法的字节码指令,它读取字段 a 的值,加 1,然后返回结果。


  • descriptor: I

类型为I, I即是int类型,关于字节码的类型对应如下:

标识字符含义
B基本类型byte
C基本类型char
D基本类型double
F基本类型float
I基本类型int
J基本类型long
S基本类型short
Z基本类型boolean
V特殊类型void
L对象类型,以分号结尾,如Ljava/lang/Object;

(10)、行号表

  • LineNumberTable:提供了源代码行号和字节码指令之间的映射。


(11)、源文件

  • SourceFile: "Test.java":指示这个 .class 文件是由 Test.java 源文件编译而来的。

这个输出结果提供了 Test.class 文件的详细内部结构,包括字段、方法、访问控制、版本信息等。通过这些信息,可以更好地理解 Java 类的编译过程和字节码的细节。


五、分析try-catch-finally


public class TestCode {
    public int foo() {
        int x;
        try {
            x = 1;
            return x;
        } catch (Exception e) {
            x = 2;
            return x;
        } finally {
            x = 3;
        }
    }
}

执行命令:

javac TestCode.java
javap -verbose -p TestCode.class

内容如下:

  Last modified 2024年5月26日; size 418 bytes
  SHA-256 checksum 0d58e986cce436cf5dd634bcfabb39b75afaddaa863d596c1e874f3571832952
  Compiled from "TestCode.java"
public class TestCode
  minor version: 0
  major version: 61
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #9                          // TestCode
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Class              #8             // java/lang/Exception
   #8 = Utf8               java/lang/Exception
   #9 = Class              #10            // TestCode
  #10 = Utf8               TestCode
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               foo
  #14 = Utf8               ()I
  #15 = Utf8               StackMapTable
  #16 = Class              #17            // java/lang/Throwable
  #17 = Utf8               java/lang/Throwable
  #18 = Utf8               SourceFile
  #19 = Utf8               TestCode.java
{
  public TestCode();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  public int foo();
    descriptor: ()I
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=5, args_size=1
         0: iconst_1
         1: istore_1
         2: iload_1
         3: istore_2
         4: iconst_3
         5: istore_1
         6: iload_2
         7: ireturn
         8: astore_2
         9: iconst_2
        10: istore_1
        11: iload_1
        12: istore_3
        13: iconst_3
        14: istore_1
        15: iload_3
        16: ireturn
        17: astore        4
        19: iconst_3
        20: istore_1
        21: aload         4
        23: athrow
      Exception table:
         from    to  target type
             0     4     8   Class java/lang/Exception
             0     4    17   any
             8    13    17   any
            17    19    17   any
      LineNumberTable:
        line 5: 0
        line 6: 2
        line 11: 4
        line 6: 6
        line 7: 8
        line 8: 9
        line 9: 11
        line 11: 13
        line 9: 15
        line 11: 17
        line 12: 21
      StackMapTable: number_of_entries = 2
        frame_type = 72 /* same_locals_1_stack_item */
          stack = [ class java/lang/Exception ]
        frame_type = 72 /* same_locals_1_stack_item */
          stack = [ class java/lang/Throwable ]
}
SourceFile: "TestCode.java"

我们重点解读名为 foo 的 Java 方法的字节码信息。

下面是对这个输出的详细解析:

  1. 方法签名
    • public int foo();:定义了一个名为 foo 的公共方法,它返回一个整数值。
  2. 方法描述符
    • descriptor: ()I:表示这个方法没有参数,并返回一个 int 类型的值。
  3. 访问标志
    • flags: (0x0001) ACC_PUBLIC:表示这个方法是公开的。
  4. 字节码指令
    • Code:包含了实际执行的方法体的字节码指令。
    • stack=1, locals=5, args_size=1:表示这个方法在执行时,操作数栈的最大深度是 1,局部变量表的大小是 5(包括 this 指针和方法参数),参数大小是 1(对于实例方法,this 指针算作第一个参数)。
  5. 字节码指令详解
    • iconst_1:将整数 1 推送到栈上。
    • istore_1:将栈顶的整数值存储到局部变量 1 中。
    • iload_1:从局部变量 1 中加载整数值到栈上。
    • istore_2:将栈顶的整数值存储到局部变量 2 中。
    • iconst_3:将整数 3 推送到栈上。
    • istore_1:将栈顶的整数值存储到局部变量 1 中。
    • iload_2:从局部变量 2 中加载整数值到栈上。
    • ireturn:将栈顶的整数值作为返回值结束方法。
    • astore_2:将栈顶的引用类型值存储到局部变量 2 中。
    • iconst_2istore_1istore_3aloadathrow:这些指令涉及到异常处理,athrow 指令会抛出异常。
  6. 异常表
    • Exception table:列出了方法中可能抛出的异常及其处理程序的位置。
    • fromtotargettype:分别表示异常发生的起始指令、结束指令、跳转目标指令和异常类型。
  7. 行号表
    • LineNumberTable:提供了源代码行号和字节码指令之间的映射,方便调试。
  8. StackMapTable
    • StackMapTable:在 JDK 7 及以后版本中,用于替代之前的 Exceptions 属性和 LineNumberTable,提供了更详细的栈映射信息,用于支持新的异常表和行号信息。
  9. 源文件
    • SourceFile:指示这个 .class 文件是由哪个 .java 源文件编译而来的。

这个输出结果提供了 foo 方法的字节码指令和相关元信息,包括方法的访问权限、返回类型、局部变量和操作数栈的使用情况、异常处理以及源代码行号映射等。通过这些信息,可以深入理解 Java 方法的执行细节和异常处理机制。


六、结语

字节码不仅支持Java语言,还支持所有编译到字节码的JVM语言,如Groovy、Scala、Kotlin等。此外,字节码层面的优化可以显著提高程序性能。

字节码是Java程序的灵魂,掌握了字节码,就掌握了程序性能的钥匙。本文深入探讨了Java字节码的内部结构和工作原理,然而,字节码的世界远比我们所见的要深邃。

在下一篇文章中,我们将揭开JVM调优的神秘面纱,探索如何通过字节码优化让Java程序运行如飞。敬请期待!


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

联发科MT8370平台Genio 510物联网应用程序处理器详细规格参数

MT8370是一款高度集成、功能强大的平台&#xff0c;专为各种人工智能(AI)和物联网(IoT)用例而设计&#xff0c;这些用例需要高性能边缘处理、先进的多媒体和连接功能、多个高分辨率摄像头、连接的触摸屏显示器以及多任务高级操作系统(HLOS)的使用。http://Genio 510 (MT8370) E…

unity制作app(11)--dropdown统一字体

下拉栏统一字体只能在执行的时候&#xff0c;而且要深入到content的最下层 全改以后 这样是无法保存的&#xff0c;但此时已经具备了找content的思维&#xff0c;在非play状态下做如下修改 其他下拉栏照改就可以了。

数组的定义、顺序存储及特殊矩阵的存储

目录 一、数组的定义 1.1概念 1.2抽象数据类型定义 二、数组的顺序存储 2.1一维数组元素的存储位置 2.2二维数组元素的存储位置 2.3三维数组元素的存储位置 三、特殊矩阵的压缩存储 3.1相关概念 3.2对称矩阵 3.3三角矩阵 3.4对角矩阵&#xff08;带状矩阵&#xff0…

HBase安装

安装HBase 提示&#xff1a;需要安装好hadoop和zookeeper 安装zookeeper可参考 一、确定HBase版本 去网站确认 https://hbase.apache.org/book.html#hadoop二、下载HBase安装包 去清华大学镜像站下载 https://mirrors.tuna.tsinghua.edu.cn/apache/hbase/三、安装HBase …

FTP协议——LightFTP安装(Linux)

1、简介 LightFTP是一个轻量级的FTP&#xff08;File Transfer Protocol&#xff0c;文件传输协议&#xff09;客户端软件。FTP是一种用于在网络上传输文件的标准协议&#xff0c;允许用户通过TCP/IP网络&#xff08;如互联网&#xff09;在计算机之间进行文件传输。 2、步骤…

运维笔记.Docker镜像分层原理

运维专题 Docker镜像原理 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/artic…

10大领域应该怎么记?

文章目录 5大过程组10大领域49个过程输出输入工具与技术 参考文档&#xff1a; https://mp.weixin.qq.com/s/BJ-Dpn0zxTP0TCbeoJXb9A 5大过程组 启动、规划、执行、监控、收尾 10大领域 巧记&#xff1a;【挣饭进城市&#xff0c;咨购风菜干】【狗子整范进—成人风采】 整…

前端nvm、nodejs、npm、cnpm、yarn安装教程(超详细图文,含卸载旧的nodejs,安装及环境变量配置)

最近换了新电脑&#xff0c;一开始在网上找了一个教程让下载nvm-noinstall.zip 压缩包解压使用&#xff0c;踩坑了&#xff0c;过程复杂最后报错无法用。 后来搜到下文教程&#xff0c;直接使用nvm。exe进行安装&#xff0c;方便快捷。下面这个文章写的很详细&#xff0c;从如何…

SwiftUI中TabView(PageTabViewStyle的用法及无限滚动组件infinity carousel)

上一篇文章主要介绍了TabView的基本用法以及一些外观样式的设置&#xff0c;本篇文章主要介绍一下PageTabViewStyle样式下的TabView&#xff0c;该样式下的TabView允许用户整页滑动界面&#xff0c;在UIKit中我们用UIScrollView和UICollectionView制作滚动组件&#xff0c;本文…

家政项目day2 需求分析(模拟入职后熟悉业务流程)

目录 1 项目主体介绍1.1 项目背景1.2 运营模式1.3 项目业务流程 2 运营端需求2.1 服务类型管理2.2 服务项目&#xff08;服务&#xff09;管理2.3 区域管理2.4 区域服务管理2.5 相关数据库表的管理2.6 设计工程结构2.7 测试接口&#xff08;接口断点查看业务代码&#xff09; 1…

Java实现链表

链表 前言一、链表的概念及结构二、链表的分类三、链表的实现无头单向非循环链表实现无头双向链表实现具体代码 四、链表习题五、顺序表和链表的区别 前言 推荐一个网站给想要了解或者学习人工智能知识的读者&#xff0c;这个网站里内容讲解通俗易懂且风趣幽默&#xff0c;对我…

Autodesk Flame 2025 for Mac:视觉特效制作的终极利器

在数字时代&#xff0c;视觉特效已经成为电影、电视制作中不可或缺的一部分。Autodesk Flame 2025 for Mac&#xff0c;这款专为视觉特效师打造的终极工具&#xff0c;将为您的创作提供无尽的可能。 Autodesk Flame 2025 for Mac拥有强大的三维合成环境&#xff0c;能够支持您…

05.配置tomcat管理功能

认证失败&#xff0c;需要配置tomcat-users.xml文件 配置用户信息 [rootweb01 /application/tomcat/conf\]# tail tomcat-users.xml <role rolename"admin-gui"/> <role rolename"host-gui"/><role rolename"mana…

数学建模--LaTeX的基本使用

目录 1.回顾 2.设置这个页眉和页脚 3.对于字体的相关设置 4.对于这个分级标题的设置 5.列表的使用 6.插入图片 1.回顾 &#xff08;1&#xff09;昨天我们了解到了这个latex的使用基本常识&#xff0c;以及这个宏包的概念&#xff0c;区域的划分&#xff0c;不同的代码代…

PCL 法向量加权的RANSAC拟合分割平面

目录 一、算法原理1、原理概述2、主要函数二、代码实现三、结果展示四、相关链接本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 1、原理概述

树与二叉树的概念介绍

一.树的概念及结构&#xff1a; 1.树的概念&#xff1a; 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的 有…

IDEA 上方添加左右箭头按钮

IDEA 版本&#xff1a;2021.3.3 按钮&#xff1a; 左箭头&#xff08;Back&#xff09;&#xff08;快捷键&#xff1a;Ctrl Alt 左箭头&#xff09; 右箭头&#xff08;Forward&#xff09;&#xff08;快捷键&#xff1a;Ctrl Alt 右箭头&#xff09; 日常写代码中经常…

Java与GO语言对比分析

你是不是总听到go与java种种对比&#xff0c;其中在高并发的服务器端应用场景会有人推荐你使用go而不是 java。 那我们就从两者运行原理和基本并发设计来对比分析&#xff0c;看看到底怎么回事。 运行原理对比 java java 中 jdk 已经帮我们屏蔽操作系统区别。 只要我们下载并…

开源金融AI代理平台FinRobot;支持多翻译引擎和模式的高效浏览器翻译开源插件;使用自然语言控制生成视频的通用世界模型

✨ 1: finrobot FinRobot 是一个基于大语言模型的开源金融AI代理平台&#xff0c;适用于多种金融应用。 FinRobot是一个综合性的AI代理平台&#xff0c;超越了原有的FinGPT&#xff0c;旨在满足金融行业的多元化需求。它集成了各种AI技术&#xff0c;不仅仅局限于语言模型&am…

APM2.8飞控

ArduPilotMega 主控可应用于 固定翼、直升机、多旋翼、地面车辆 APM2.8飞控供电有两种 1.电流计供电&#xff0c; 2.带BEC&#xff08;稳压功能&#xff09;的电调供电 ArduPilotMega 内部的硬件结构图&#xff1a; 调试时&#xff0c;不要使用向导&#xff0c;由于向导功能不…