Java 解释字节码之前的静态块执行。如何?

Java 解释字节码之前的静态块执行。如何?,java,jvm,Java,Jvm,当我们说javatest时,类加载器将把.class文件加载到方法区域,静态变量(如果有)被初始化为相应的赋值,静态块将被执行 在java中,执行意味着代码必须由java解释器解释。但是静态块在没有解释的情况下是如何执行的呢?它仍然处于类加载阶段,不是吗 但在大多数博客和视频中,他们说一旦类加载完成,就会创建新的线程,它会寻找主方法并开始执行它。在我看到的所有博客中,一旦主方法开始执行,解释器就会出现 class Test { static int x = 10; stati

当我们说
javatest
时,类加载器将把.class文件加载到方法区域,静态变量(如果有)被初始化为相应的赋值,静态块将被执行

在java中,执行意味着代码必须由java解释器解释。但是静态块在没有解释的情况下是如何执行的呢?它仍然处于类加载阶段,不是吗

但在大多数博客和视频中,他们说一旦类加载完成,就会创建新的线程,它会寻找主方法并开始执行它。在我看到的所有博客中,一旦主方法开始执行,解释器就会出现

class Test {

    static int x = 10;

    static {
         int y = 10;
        System.out.println(x);
    }

    public static void main(String[] args) {

    }
}

解释器的存在是一个与描述程序行为无关的实现细节。原则上,JVM完全可以没有解释器,因为它可能只有一个编译器在执行之前将所有字节码转换为本机代码,并且仍然实现正确的行为。当前的桌面JVM和服务器JVM都有,以混合模式执行代码

因此,博客和视频提到解释器的存在是执行代码的一种方式也是不相关的,代码的执行总是意味着执行代码的技术手段的存在,比如解释器或编译器

实际行为已在中指定:

§12.4.1. 初始化发生时 类或接口类型T将在第一次出现以下任一情况之前立即初始化:

  • T
    是一个类,并创建了
    T
    的实例
  • 调用由
    T
    声明的
    static
    方法
  • 分配了由
    T
    声明的
    静态
    字段
  • 使用由
    T
    声明的
    static
    字段,该字段不是常量变量()
  • T
    是一个顶级类(),执行一个词汇嵌套在
    T
    ()中的
    assert
    语句()。ª
初始化一个类时,它的超类将被初始化(如果它们以前没有被初始化),以及声明任何默认方法()的任何SuperInterface()(如果它们以前没有被初始化)。接口的初始化本身不会导致其任何超级接口的初始化

这最后一个项目符号已从较新的规范中删除

由于调用
main
方法是调用“您的类声明的
static
方法”,因此它意味着在调用之前初始化该类。从上一节可以看出,如果包含
main
方法的类具有未初始化的超类,则它们甚至在该类之前就已初始化

对于标准Java启动器,事件的顺序是

  • 主线程被创建
  • 主线程加载指定的应用程序类
  • 应用程序类的超类已初始化(如果尚未初始化)
  • 应用程序类已初始化
  • 在应用程序类上调用方法
    staticvoidmain(String[])
术语“应用类”和“主要类”可以互换

请注意,此列表仅用于将这些事件按正确顺序排列。幕后发生的事件多得多。显然,为了让应用程序类加载器加载应用程序类(以名称命名),类
String
class
ClassLoader
必须已经加载并初始化,这也意味着它们的超类
对象
在此之前已经初始化。主线程的存在意味着类
thread
的加载和初始化。所有这些类都在幕后使用其他类


您可以使用
-verbose:class
选项运行应用程序,以查看哪些类已在应用程序类之前加载。

请正确编写。没有人会理解你想说的话。你是否声称在
main()
之前不能或不会执行任何代码?这当然不是真的,不管你从“bolgs”读到什么。嗨,Kayaman,到处都说在主方法执行开始之前发生的任何事情都是类加载阶段。但是在类加载阶段静态块如何执行?执行代码的bcs必须被ryt解释。您假设代码不能在类加载阶段执行。您的假设是错误的。加载类后,将执行其静态块。主线程在这里根本不相关。主要的方法不是第一个执行的代码。“原则上,JVM可能根本没有解释器,因为它可能只有一个编译器将所有字节码翻译成本机代码”-IIRC,GCJ就是这样做的-尽管它已经是一个死项目很多年了。@MichaelBerry是的,GCJ似乎已经死了,但另一方面,最近的JDK又开始尝试提前编译;看……嘿,这很有趣——那只不知怎么从我身边经过。我认为GCJ注定要失败,不是因为它的目标是本地执行,而是因为它背后的团队很小,而且他们有一个巨大的、不断发展的任务。看到AOTC未来的发展方向肯定会很有趣。谢谢@Holger,它帮了很多忙。在您的回答中,您提到了以下几行:“JVM根本没有解释器,因为它可能只有一个编译器,在执行“编译器”和“JIT编译器”之前将所有字节码转换为本机代码?Right它可以是JIT编译器或AOT编译器。当前JVM有一个解释器和一个JIT编译器。