java -verbose:class显示加载了servlet,但只有在访问servlet时才初始化静态内容

时间:2014-04-14 17:11:59

标签: java servlets classloader

我认为我在这里弄错了。

我有一个简单的servlet,带有一个打印一些消息的静态块。因此,据我所知,当servlet类首次加载到jvm时,应该处理静态块。

我正在使用嵌入式jetty并使用-verbose:class jvm选项启动jetty服务器。

我可以在输出中看到,在我第一次访问此servlet并查看消息之前很久就加载了Servlet类。

但据我了解,静态块应该在加载类之后立即初始化。我在哪里错了?

2 个答案:

答案 0 :(得分:2)

现在......当你说加载了Servlet类时,你指的是你自己的类还是javax.servlet.Servlet接口?

如果您没有在web.xml中的servlet声明中指定<load-on-startup>并将其设置为非零值,则jetty只是跟随Servlet specification并且不加载它直到它为止第一次使用。


(以下是我在开始查看Servlet规范之前首先编写的内容,根据您是否<load-on-startup>设置为非零值,它可能仍然相关)

根据Java规范§8.7

  

在类初始化时执行类中声明的静态初始化程序(第12.4.2节)。

Java规范的

§12.4.1(§12.4.2的概述)说,如果发生以下某种情况,则会初始化类T

  • T是一个类,并创建了T的实例。
  • T是一个类,调用T声明的静态方法。
  • 分配了T声明的静态字段。
  • 使用T声明的静态字段,该字段不是常量变量(§4.12.4)。
  • T是顶级类(第7.6节),并且执行在T(第8.1.3节)内词法嵌套的断言语句(第14.10节)。

因此,如果jetty实际上从未对类执行任何操作,则静态初始化程序将无法运行

答案 1 :(得分:2)

Java Language Specification

  

Java虚拟机动态加载链接初始化   类和接口。 加载是查找二进制文件的过程   具有特定名称和类的类或接口类型的表示   从该二进制表示创建一个类或接口。链接   是一个获取类或接口并将其组合到一起的过程   Java虚拟机的运行时状态,以便它可以   执行。 类或接口的初始化包括执行   类或接口初始化方法<clinit>(§2.9)。

最后一部分<clinit>是运行static初始值设定项的地方。

您使用的java launcher option

-verbose:class

简单地

  

显示有关每个已加载类的信息。

因此,您的类是作为加载类路径条目的Web应用程序的一部分加载的,但是在Jetty实例化它之前它不会被初始化,以便它可以使用该对象来处理请求。