0

A couple of days ago, I upgraded Jenkins to version 1.643. Before, we were using Jenkins 1.593. Starting with Jenkins 1.612, Jenkins requires Java 7, see changelog, announcement and issue. Our Jenkins server has Java 8.

I have a Maven project consisting of submodules. In the job configuration in Jenkins, I have configured the build to use JDK 1.6.

When looking at the build environment, it's indeed 1.6:

JAVA_HOME=/var/lib/jenkins/tools/hudson.model.JDK/1.6

One of the submodules fails to build on Jenkins, with this error:

[ERROR] /var/lib/jenkins/<REDACTED>.java:[15,-1] cannot access java.lang.Object
bad class file: java/lang/Object.class(java/lang:Object.class)
class file has wrong version 52.0, should be 50.0

According to what I can Google, class file version 52.0 is JDK 1.8 while the compiler is expecting version 50.0, which is JDK 1.6. I assuming that class file 52.0 refers to rt.jar (Java Runtime) which contains java.lang.Object (see also pom.xml snippet below).

I have found this SO question (and others that are duplicate of it), but they are all in the context of someone building from their IDE (IntelliJ) or from command prompt, and after reading them, I don't see how I could apply the suggested solutions. They involve setting $JAVA_HOME, which is already done by Jenkins.

My question is different because the issue is in the context of Jenkins (and Maven), and only occurred after the Jenkins upgrade. When I execute mvn clean install on my own desktop (with JDK 1.8), the error does not occur. If I execute the file command on the offending class file, but on the desktop where compilation succeeded, I get compiled Java class data, version 50.0 (Java 1.6). For me, this confirms that my pom.xml is (probably) still correct and it's (probably) a Jenkins configuration issue.

That specific submodule has this in the pom.xml, which may or may not be relevant:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
                <compilerArguments>
                    <verbose />
                    <bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
                </compilerArguments>
            </configuration>
        </plugin>
    </plugins>
</build>

So, as you can see, it takes rt.jar from the current $JAVA_HOME so it can cross compile with a target of 1.6.

I'm a bit lost about the origin of this Java 8. Before the Jenkins upgrade, we were already using Java 8 on the server and cross compiling with a target of Java 6. What am I missing here?

EDIT

Do I even need this? If I comment out

                <compilerArguments>
                    <verbose />
                    <bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
                </compilerArguments>

in pom.xml, I can still cross compile on my desktop and the class files are still version 50.0.

EDIT

When I take that part out, the build does not fail any more. Which means I solved it myself.

I want to change the question to: why did it fail in the first place? And why didn't it fail before on Jenkins 1.593?

Community
  • 1
  • 1
Amedee Van Gasse
  • 7,280
  • 5
  • 55
  • 101

2 Answers2

0

I changed my pom.xml to exactly how it is described in this SO answer: Maven release plugin: specify java compiler version

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.3</version>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
                <encoding>UTF-8</encoding>
                <bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
            </configuration>
        </plugin>
    </plugins>
</build>

As you can see:

  • I explicitly set the groupId
  • I explicitly set the version to the latest version, 3.3
  • The configuration parameters are formatted a bit differently.

My educated guess is that the Maven on the Jenkins server didn't pick up configuration inside compilerArguments and was only happy when it is directly inside configuration. I leave it to the comments to explain how and why, but for me the issue is solved.

Community
  • 1
  • 1
Amedee Van Gasse
  • 7,280
  • 5
  • 55
  • 101
0

I think you have a few errors in your assumptions.

  1. compilerArguments is deprecated. It's been superseded by compilerArgs.

  2. Like you can see from compiler plugin documentation, compilerArguments/compilerArgs is meant to be used only for arguments not supported by configuration section itself. As bootclasspath is supported, using it in compilerArgs/compilerArguments section is generally incorrect.

  3. compilerArgs/compilerArguments is only used if fork is set to true, which was not correct for your configuration.

The third point was probably the most important reason why it didn't work for you. Using configuration section for your use case there should be no issues, and indeed based on your question/answer, this seems to be the case.

Also note that java.home is not JAVA_HOME. I've expanded on that on my other answer here. I'd guess that is related to why you see changes between Jenkins versions.

Community
  • 1
  • 1
eis
  • 51,991
  • 13
  • 150
  • 199
  • Ok, so if I understand it correctly: the `$JAVA_HOME` I found is something that Jenkins knows about *before* it starts a job, but isn't necessarily the same as the JRE/JDK that Maven is using *at the precise moment when the event occured that triggered my question*, because of what the compiler plugin does. I could have set my job to build with JDK 1.8, set the compiler plugin to build for 1.6 with the configuration as in the answer, and I would still have a valid build. Is that a correct assumption? – Amedee Van Gasse Jan 19 '16 at 10:15
  • Great. This means I can move some stuff to the parent pom and simplify the other poms. – Amedee Van Gasse Jan 19 '16 at 10:52
  • test it first though - there might always be something else that interferes with it. – eis Jan 19 '16 at 11:09
  • Of course. That's what feature branches are for! :) – Amedee Van Gasse Jan 19 '16 at 11:11
  • @AmedeeVanGasse to clarify: your bootclasspath would still need to point to rt.jar of a previous JDK. So while you can run it on JDK 1.8, you'd still need rt.jar from JDK 1.6 somewhere and then point to it. Unfortunately. – eis Jan 19 '16 at 13:04
  • Yes, that's what I thought already. Makes sense somehow. It's the actual pointing that I am unsure about and experimenting with. – Amedee Van Gasse Jan 19 '16 at 13:06