A small helper library to give users a friendly message when they're using a version of Java that's too old
Does your app require a recent version of Java? Are your users likely to have only old versions of Java installed?
If users run code with a version of Java that's too old, the fatal error message
isn't friendly - it starts like this:
java.lang.UnsupportedClassVersionError : Unsupported major.minor version 51.0
...
and, because it's a stacktrace, carries on for several lines lines like this...
Exception in thread "main" java.lang.UnsupportedClassVersionError: org/eclipse/jgit/lib/Repository : Unsupported major.minor version 51.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:637)
at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
...
...that's a bad message to show your user! UnsupportedClassVersionError
means
that their version of Java is too old, and major.minor version 51.0
means they
need at least Java version 7
to get the code to run - but they probably won't know that.
Use Newer Java is a small library compiled for
old
versions of Java and designed for command-line Java tools like
the BFG Repo-Cleaner,
that are distributed as a single uber-jar containing all dependencies
and run with the java -jar my-app.jar
invocation.
It will display friendly messages like this to your user:
Looks like your version of Java (1.8) is too old to run this program.
You'll need to get Java 9 or later.
If the user has a version of Java that's new enough, the user won't see the message, and Use Newer Java will just pass along the command line arguments to the main class of your command-line app, which will run normally. Your app can be compiled for the latest version of Java - Use Newer Java will be the only code targeting old versions of Java in your app.
UseNewerJava
is compiled targeting Java 5, meaning that it will execute
correctly on most Java VMs users are likely to have these days.
- Include
use-newer-java
as a dependency in your project - Set the
Main-Class:
field in the manifest of your built jar touse.newer.java.Version8
oruse.newer.java.Version9
, etc as appropriate. - Set the
Main-Class-After-UseNewerJava-Check:
in your jar manifest to the normal main class of your app- Use Newer Java will follow this setting, and invoke this code after making it's check.
That's it.
See https://github.com/rtyley/bfg-repo-cleaner/commit/a1cf8694f for an
example of adding UseNewerJava
to a CLI app within an SBT build. It
shouldn't be too hard to take the same approach with Maven, Gradle builds
etc.