3

I understand the issue regarding this type of error. I would like my program to be able to detect the java version running and provide a more elegant message to the user rather than the somewhat cryptic 'Exception in thread "main" bla bla bla' message. I can detect the Java version running, but it appears that my program never gets far enough to run my checking code.

In short... how can my program catch this error, present a message and exit gracefully?

Paul
  • 117
  • 1
  • 1
  • 9
  • 1
    If you obtain this error at program _startup_, then no chance: your code will not even be executed. – fge Jan 11 '13 at 19:15
  • @fge, what about own `ClassLoader`? – Andremoniy Jan 11 '13 at 19:18
  • @Andremoniy to run `main()`? How would you plugin your classloader before `main()` runs? – fge Jan 11 '13 at 19:19
  • @fge, yes it is possible. Just some googling and you could find such decisions. – Andremoniy Jan 11 '13 at 19:21
  • 2
    @Andremoniy, you seem to be the expert on that, so if you could spare us the googling and add a short description of how you do that to your answer, that would be awesome. – us2012 Jan 11 '13 at 19:22
  • 1
    The key question: are you building the class that has the incorrect version? Because if you are, just rebuild it with the correct version (using the `-target` compiler option). – parsifal Jan 11 '13 at 19:25
  • 2
    @us2012 http://stackoverflow.com/questions/6366288/how-to-change-default-class-loader-in-java – Andremoniy Jan 11 '13 at 19:25
  • @Andremoniy Changing the default class loader won't help unless it is compiled with -target appropriately, which is the necessary and sufficient solution to the entire problem, *without* changing the default classloader. – user207421 Jan 11 '13 at 23:39
  • @EJP, if you read my answer more carefully, you will see, that I mentioned about compiling class loader withmore eaearlier version of Java. Furthermore, you could not recompile most of the used Jars, which could cause major.minor ... error – Andremoniy Jan 12 '13 at 05:58

2 Answers2

0

So it's java.lang.UnsupportedClassVersionError. It is (evidently a descendant of the Error class in Java) which subclasses java.lang.ClassFormatError which in turn subclasses java.lang.LinkageError (which is a direct subclass of java.lang.Error)). This error is thrown in the cases when the JVM (Java Virtual Machine) attempts to read a class file and finds that the major and minor version numbers in the particular class file are not supported. This happens in the cases when a higher version of Java Compiler is used to generate the class file than the JVM version which is used to execute that class file.

This is quite easier to understand – how can the compiler have the information at the time of compilation about which version of JVM would be used execute the compiled class file? It can't, right? So is the case with other errors as well. This is the reason why all the Errors are unchecked.

Why you even give user the chance to see this error message! This as you say "cryptic" message will only be emitted out when you are using an earlier version of JVM to execute the class file than the corresponding version of compiler you used to compile the source code. Now, why would you do that?

Amar
  • 11,930
  • 5
  • 50
  • 73
  • Why `Errors` are never detected? Can't understand your statement. They could be catches in `try... catch (Error err) ...` – Andremoniy Jan 11 '13 at 19:19
  • Why are you talking about compile time? This error is thrown at runtime. – parsifal Jan 11 '13 at 19:24
  • 2
    Your wording is wrong. It is not that errors are never detected, it is that they are unchecked exceptions. The fact that an exception is checked and unchecked only has influences at _compile time_ (that is, no need to catch/throw them), and as a consequence they go up right up to `main()` unless you catch them. – fge Jan 11 '13 at 19:25
  • Amar, as OP, my hope is to catch the problem, report it and exit. The reason is that I may distribute my program to someone who is running an earlier java than my compiled jar. Providing a message and a graceful exit may save some head-scratching for the user. – Paul Jan 11 '13 at 19:34
  • 2
    You can ensure that by compiling using a super-old version of compiler! Just kidding... But seriously you can provide the info that this jar can be used only with x+ version of JVM. This should be made known to the user beforehand only instead of them using the jar and then getting into this error, though with a nice message! – Amar Jan 11 '13 at 19:39
  • 3
    @Paul - a better approach might be to change the way that your application is distributed. For example, using [Java WebStart](http://docs.oracle.com/javase/tutorial/deployment/webstart/index.html). I think you'll find that, even if you invest a lot of energy to give a pleasant message before exiting, your users will find something else to be confused about (such as not having a JVM at all). – parsifal Jan 11 '13 at 19:41
  • OK. I guess the bottom line is this type of error occurs **before** the program actually gets going, resulting in program termination. As such, since the program has ended really before it's begun, there's no way that the program can deal with the error. @parsifal, I'll take your advice. Thanks to all who contributed their thoughts and experience to this thread. – Paul Jan 12 '13 at 03:04
  • @EJP - actually, it *is* a JVM launcher error: the person who wants to run the app has a JVM that is incapable of doing so. For all I know, they're running a 1.2 JVM, and no sane person is going to recompile their app to support that. JWS allows you to specify the minimum required version, and *it* will tell the user that they need to upgrade. – parsifal Jan 14 '13 at 15:44
0

This exception is throwing from ClassLoader, so I could suggest you write your own version of ClassLoader which will backtrace such errors.

UPD: More specifically you can try to override method defineClass, catch there such exception and wrap it in convenient way.

UPD-2: As I mentioned in comments, and as us2012 reformulated my idea (thanks to him), you have to compile your classloader with a -target that is guaranteed to be lower than the user's VM version

Community
  • 1
  • 1
Andremoniy
  • 34,031
  • 20
  • 135
  • 241
  • 1
    Will that work? Your own ClassLoader is likely to be incompatible with the user's JVM, just like the code you were trying to run in the first place. Am I wrong? – us2012 Jan 11 '13 at 19:19
  • It's not an `Exception` at first place. It's an `Error` and they are never detected at compile time! – Amar Jan 11 '13 at 19:21
  • @us2012 what do you mean by *own ClassLoader is ... incompatible with the user's JVM'? Can not understand. You could use your own class loaders, it is not deprecated. – Andremoniy Jan 11 '13 at 19:22
  • @Amar, you are wrong. Errors also could be detected in simple `try...catch`. Read manuals. – Andremoniy Jan 11 '13 at 19:22
  • 2
    It depends on why the error is being thrown. If it's code that you've compiled, then yes, you're going to get the same error with a classloader. If it's a third-party library, then the classloader approach will work (because you compile the classloader with an acceptable -target). – parsifal Jan 11 '13 at 19:23
  • @parsifal This error throws by default class loader. If you able to replace it, you able to handle such events. Just compile code of that class loader in minor version of Java to be sure, that it could be run. – Andremoniy Jan 11 '13 at 19:30
  • 1
    @Andremoniy , ah but that is the important point, that you have to compile your classloader with a `-target` that is guaranteed to be lower than the user's VM version! You should add that to your answer. (As an aside, can a single .jar contain classes that were compiled with different `-target`s ?) – us2012 Jan 11 '13 at 19:31
  • If you can compile the classloader with -target, why not compile the entire application with -target, solve the *actual* problem, and avoid the classloader altogether? – user207421 Jan 11 '13 at 23:43
  • @EJP , because you can not recompile possible used libraries – Andremoniy Jan 12 '13 at 05:53