静态块未在JDK 7中执行,“未找到主要方法”,但在JDK 1.5中有效

我写了一个带有一个静态块的简单类

class Hello { static { System.out.println("Hello"); System.exit(0); } } 

当我使用jdk1.5运行它时,静态块正在执行

 C:\apps\Java\jdk1.5.0_21\bin>javac Hello.java C:\apps\Java\jdk1.5.0_21\bin> C:\apps\Java\jdk1.5.0_21\bin> C:\apps\Java\jdk1.5.0_21\bin> C:\apps\Java\jdk1.5.0_21\bin>java Hello Hello 

但是当我使用jdk1.7运行它时,我得到了以下错误

 C:\Program Files (x86)\Java\jdk1.7.0_02\bin> C:\Program Files (x86)\Java\jdk1.7.0_02\bin>javac Hello.java C:\Program Files (x86)\Java\jdk1.7.0_02\bin>java Hello Error: Main method not found in class Hello, please define the main method as: public static void main(String[] args) 

任何人都可以对JDK 5和JDK 7中的这种行为改变有所了解吗?

提前致谢!!

Java 7在加载类之前查找main方法 。 这是以前java版本的行为更改,因此您的静态块未执行。 在以前的版本中,行为是JRE用于在加载类之后和执行静态块之后查找main方法。

是的,在jdk7中。 不首先执行静态块。 它首先查找应用程序中的入口点。

因此,它首先检查public static void main(String a[]) ,如果此方法不存在,则不会执行静态块。

通过JLS 12.1 :

Java虚拟机通过调用某个指定类的方法main来开始执行,并向其传递一个参数,该参数是一个字符串数组。 在本规范的示例中,第一类通常称为Test。

执行类Test的方法main的初始尝试发现未加载类Test – 也就是说,Java虚拟机当前不包含此类的二进制表示。 然后,Java虚拟机使用类加载器来尝试查找这样的二进制表示。

Java 7查找public static main(String[] args)方法,该方法是应用程序的入口点,然后加载类,而Java 6则加载类,然后查找main方法。

您可能需要在类中为JDK7设置public static void main(String[] args){ }方法。 在JDK7中,在静态块之前检查main方法的存在,如果找不到,则得到exception。

程序没有执行,因为从JDK 1.7 oracle已经对静态块和静态变量调用方法施加了限制,如果你的程序没有带有正确签名的main方法但是静态块和方法总是先执行。作为内存管理静态变量在类加载时完成。

如果仔细阅读JLS第12章(版本5或7),则不会在“main”类的静态初始化发生时指定。 确实有一个Bug报告抱怨这个。

指定的是在调用入口点方法之前将初始化“main”类(并且将运行静态初始化器)。 这在JLS 12.4.1中有详细说明

我无法解释为什么他们改变了这一点,或者找到他们记录变化的地方。 但显然它确实发生了变化。 如果您想要真正的解释,您需要向Sun / Oracle工程师负责。

(FWIW,我认为这是一个很好的改变。发生静态初始化然后由于没有找到入口点导致程序失败是意外的行为,如果没有充分的理由, 意外是坏的。)

除非是applet或其他东西,否则你不能在没有main方法的情况下执行java程序。 我说你对jdks的观察可能是错的

高达JDK1.6: –

它首先加载类,然后加载类静态块将被执行。 然后检查要执行的main方法。

JDK1.7起:

它首先检查main方法是否可用。

 if available then first execute static and then main method will be executed. if not available throw error