Java 如何抓住';不支持的major.minor版本';错误?

Java 如何抓住';不支持的major.minor版本';错误?,java,error-handling,Java,Error Handling,我理解关于这类错误的问题。我希望我的程序能够检测正在运行的java版本,并向用户提供更优雅的消息,而不是线程“main”bla bla bla“消息中有点神秘的异常。我可以检测到Java版本正在运行,但我的程序似乎永远无法运行我的检查代码 简言之。。。我的程序如何捕获这个错误,显示一条消息并优雅地退出?所以它是java.lang.UnsupportedClassVersionError。它(显然是Java中Error类的后代)是Java.lang.ClassFormatError的子类,而Jav

我理解关于这类错误的问题。我希望我的程序能够检测正在运行的java版本,并向用户提供更优雅的消息,而不是线程“main”bla bla bla“消息中有点神秘的异常。我可以检测到Java版本正在运行,但我的程序似乎永远无法运行我的检查代码


简言之。。。我的程序如何捕获这个错误,显示一条消息并优雅地退出?

所以它是
java.lang.UnsupportedClassVersionError
。它(显然是Java中
Error
类的后代)是
Java.lang.ClassFormatError
的子类,而
Java.lang.LinkageError
(它是
Java.lang.Error
的直接子类)。当JVM(Java虚拟机)试图读取一个类文件,发现特定类文件中的主版本号和次版本号不受支持时,会抛出此错误。这种情况发生在使用更高版本的Java编译器生成类文件而不是使用JVM版本执行该类文件的情况下

这很容易理解–编译器在编译时如何获得关于将使用哪个版本的JVM来执行编译的类文件的信息?不会吧?其他错误也是如此。这就是为什么所有错误都被取消选中的原因


为什么你甚至给用户机会看到这个错误消息!正如您所说,只有当您使用早期版本的JVM来执行类文件时,才会发出“神秘”消息,而不是使用相应版本的编译器来编译源代码。现在,您为什么要这样做?

这个异常是从
类加载器
引发的,因此我建议您编写自己版本的
类加载器
,它将回溯此类错误

UPD:更具体地说,您可以尝试重写方法
defineClass
,捕捉此类异常并以方便的方式将其包装


UPD-2:正如我在评论中提到的,以及我重新阐述的想法(多亏了他),你必须使用
-target
编译你的类加载器,该目标保证低于用户的VM版本

,如果你在程序启动时出现此错误,那么没有机会:你的代码甚至不会被执行。@fge,那own
ClassLoader
呢?@Andremoniy,你似乎是这方面的专家,所以如果你能省去我们的搜索,在你的答案中添加一个简短的描述,那就太棒了。关键问题是:你在构建一个版本不正确的类吗?因为如果是,只需使用正确的版本(使用
-target
编译器选项)重新构建它即可。@us2012这样行吗?您自己的类加载器可能与用户的JVM不兼容,就像您最初尝试运行的代码一样。我错了吗?首先,这不是一个例外。这是一个
错误
,在编译时从未检测到它们@us2012你所说的*自己的类加载器是什么意思。。。与用户的JVM“”不兼容?我不明白。您可以使用自己的类加载器,但这并不是不推荐的。这取决于抛出错误的原因。如果您编译的是代码,那么是的,您将在类加载器中得到相同的错误。如果是第三方库,那么类加载器方法将起作用(因为您使用可接受的-target编译类加载器)。@Andremoniy,啊,但这是重要的一点,您必须使用
-target
编译类加载器,这保证低于用户的VM版本!你应该把它加到你的答案里。(顺便提一下,一个.jar是否可以包含使用不同的
-target
s编译的类?)?我听不懂你的话。它们可能在
中被捕获,请尝试。。。catch(Error err).
为什么要谈论编译时?此错误在运行时抛出。您的措辞错误。这并不是说永远不会检测到错误,而是它们是未经检查的异常。检查和取消检查异常只会在编译时产生影响(也就是说,不需要捕获/抛出它们),因此,除非捕获它们,否则它们会一直上升到
main()
。您可以通过使用超旧版本的编译器编译来确保这一点!只是开玩笑。。。但是,认真地说,您可以提供这样的信息:这个jar只能用于x+版本的JVM。这应该事先让用户知道,而不是让他们使用jar,然后进入这个错误,尽管有一个很好的消息@Paul-更好的方法可能是更改应用程序的分发方式。例如,使用。我认为您会发现,即使您在退出之前投入了大量精力来提供一条令人愉快的消息,您的用户也会发现一些其他问题让您感到困惑(例如根本没有JVM)。