3

I have a project I build using ant and eclipse which I'd like to have be compatible with Java 8.

When I try running the jar using Java 8, I get the following error:

$ /usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar hypnos.jar
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError:
org/joshuad/musicplayer/MusicPlayerUI has been compiled by a more recent version of
the Java Runtime (class file version 53.0), this version of the Java Runtime only 
recognizes class file versions up to 52.0

So it appears that it's compiling using Oracle's Java 9 (which is installed on my system) but I can't find the place in eclipse where this is designated. Everything I see seems to suggest that we're using java 8 (screenshots below).

I feel like I must be missing something, but I can't figure out where. What do I have to do to get this jar to be compatible with Java 8 / class file version 52.0?

Project > Properties > Java Build Pathenter image description here

Project > Properties > Java Compiler enter image description here

Window > Preferences > Compiler enter image description here

Right Click Ant Build File > Run As > External Tools Configuration enter image description here

Ant Build File

<project name="Hypnos Music Player" default="compile" basedir=".">
    <property name="src" location="src"/>
    <property name="build" location="build"/>
    <property name="jarFile" location="hypnos.jar"/>

    <path id="class.path">
        <fileset dir="lib">
            <include name="**/*.jar" />
        </fileset>
        <pathelement location="${jarFile}" />
    </path>

    <target name="init">
        <tstamp/>
        <mkdir dir="${build}"/>
    </target>

    <target name="compile" depends="init" description="compile the source">
        <javac fork="yes" includeantruntime="false" srcdir="${src}" destdir="${build}">
            <classpath refid="class.path" />
        </javac>
    </target>

    <target name="jar" depends="compile" description="Create a jar.">
        <jar destfile="${jarFile}" basedir="${build}">
            <manifest>
                <attribute name="Main-Class" value="org.joshuad.musicplayer.MusicPlayerUI" />
                <attribute name="Class-Path" value="lib/commons-cli-1.4.jar lib/jaad-0.8.4-nospi.jar
                                                    lib/jaudiotagger-2.2.6-SNAPSHOT.jar lib/jflac-1.2.jar
                                                    lib/jl1.0.1.jar lib/jogg-0.0.7.jar lib/jorbis-0.0.15.jar
                                                    lib/vorbisspi1.0.3.jar" />
            </manifest>
        </jar>
    </target>
</project>
Grumblesaurus
  • 3,021
  • 3
  • 31
  • 61
  • Since you are using `javac` in the Ant build the only Eclipse setting used is the External Tools Configuration. What does the 'Java > Installed JREs' show for the selected JRE? – greg-449 May 29 '17 at 07:43

2 Answers2

6

What is your $JAVA_HOME environment variable?

I recently had a similar problem and it turns out that Ant seems to ignore many settings provided by Eclipse and only uses $JAVA_HOME. I discovered this by placing the following in build.xml:

<target name="jdk_version_validation">
    <echo message="Java Version: ${java.version}" />
    <echo message="Java home: ${java.home}" />
    <echo message="JAVA_HOME: ${env.JAVA_HOME}" />
    <echo message="JAVACMD: ${env.JAVACMD}" />
</target>

Which got me this:

jdk_version_validation:
     [echo] Java Version: 1.7.0_80
     [echo] Java home: C:\Program Files\Java\jre7
     [echo] JAVA_HOME: C:\Program Files\Java\jdk1.8.0_131\
     [echo] JAVACMD: C:\Program Files\Java\jdk1.7.0_80\bin

I found that the only sure way to predict which version Ant will produce is by brute-forcing the following in build.xml:

<property name="ant.build.javac.source" value="1.7"/> 
<property name="ant.build.javac.target" value="1.7"/>

So, my recommendation to you: Try placing in your build.xml the following:

<property name="ant.build.javac.source" value="1.8"/> 
<property name="ant.build.javac.target" value="1.8"/>

Update, for the benefit of those with a variation of the problem described in the OP, to eliminate any possibility of "Eclipse fooling Ant":

  1. Go to Window > Preferences > Java > Installed JREs and try leaving only the target JRE, making sure it is the one inside the JDK folder (not the sibling one directly under the Java folder).
  2. Go to Project > Properties > Java Compiler and check Enable project specific settings, making sure that the Compiler compliance level is set to the target JRE java version.
datv
  • 585
  • 3
  • 15
1

In addition to what datv said above, I'll add from experience:

Ant's javac, java, and junit tasks have a jvm attribute that determines how to run the JDK/JRE, if fork="true". Unfortunately, it only sets the raw launcher, and doesn't change all the other settings. When I set the jvm attribute to the full path of a Java 8 JRE, turning on ant's -d switch shows that it is being used as the executable, but followed by

'-Djava.specification.version=9'
'-Dsun.boot.library.path=C:\Java\x64\jdk-9.0.1\bin'
'-Djava.home=C:\Java\x64\jdk-9.0.1'
'-Djava.runtime.version=9.0.1+11'
'-Djava.version=9.0.1'
'-Djava.library.path=...;C:\Java\x64\jdk-9.0.1\bin;.....
'-Djava.vm.version=9.0.1+11'
'-Djava.class.version=53.0'

all of which take precedence.

It turns out that Ant cares more about the JAVACMD environment variable when it starts up. In the situation above, our build framework had set JAVACMD to C:\Java\x64\jdk-9.0.1\bin\java, and the individual jvm= and executable= attributes on specific tasks were... not "ignored" really, merely pointless and misleading.

Ti Strga
  • 1,353
  • 18
  • 40