Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-37670

RemoteClassLoader: ClassFormatError c.f. UnsupportedClassVersionError

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Minor Minor
    • remoting
    • None

      When the RemoteClassLoader encounters a Java class file whose version is too high, it ends up throwing ClassFormatError.

      This comes as a nasty surprise to software packages that expect to receive (and trap, and recover from) UnsupportedClassVersionError.

      In particular, this breaks the JGit functionality in the git-client-plugin (versions 1.19.1 to 1.19.7) if it executes on a slave that's running JDK 1.6.

      (Yes, I realize that JDK 1.6 is ancient history so this particular example may be moot now, but the same general problem may reappear in the long march from 1.7 to 1.8 or 1.8 to 1.9).

      jgit-client-plugin 1.9.0 and below don't experience this problem because they didn't include the dependency that triggers this, org.eclipse.jgit:org.eclipse.jgit.java7. That dependency was added in git-client-plugin 1.19.1 with this checkin comment:

      JENKINS-30371 Distribute JGit java7 jar to allow JGit symlink support
      JGit symlink support is optional with JGit 3.7.1. It requires a copy of
      the JGit java7 jar, a Java 7 VM, and a file system which supports symbolic
      links. Including the jar file in a Java 6 environment is safe because
      the JGit code won't load the additional jar when running on Java 6.

      That last sentence is probably true in an environment where the RemoteClassLoader isn't involved (e.g. on master?) but definitely not on JDK 1.6 slaves.

      There's nothing that the git-client-plugin can (or should) do to fix this; the code that's expecting to receive and handle UnsupportedClassVersionError is in org.eclipse.jgit:org.eclipse.jgit.

      (I should probably say "was in" because newer versions of org.eclipse.jgit have made JDK 1.7 required rather than optional).

      My (quite likely clueless) 0.02 re the code in RemoteClassLoader.loadClassFile() is roughly:

      • In the case where it checks bytecodeLevel itself it should throw UnsupportedClassVersionError (not ClassFormatError)
      • In the case where it wraps try-catch around the call to defineClass(), the current catch-block for ClassFormatError also catches the UnsupportedClassVersionError subtype and ends up throwing a ClassFormatError instead. It should, somehow or other, preserve the subtype (UnsupportedClassVersionError).

      Perhaps that second path is never exercised now (because of the explicit bytecodeLevel check above)? I'm not sure. But I definitely got bitten by it today, admittedly using antique versions of Jenkins components (and JDK 1.6).

      FWIW, when I encountered that second case, the UnsupportedClassVersionError that got caught and wrapped as ClassFormatError already displayed this:

      java.lang.UnsupportedClassVersionError: org/eclipse/jgit/util/Java7FSFactory : Unsupported major.minor version 51.0

      i.e. the catch-and-wrap-in-order-to-add-the-class-name rigmarole wasn't beneficial because the class name was already there. But I haven't checked whether that's always true.

          [JENKINS-37670] RemoteClassLoader: ClassFormatError c.f. UnsupportedClassVersionError

          Oleg Nenashev added a comment -

          I agree that UnsupportedClassVersionError is a right error to be thrown in such case.
          Jenkins project does not support Java 6 starting from 1.610 (and it will likely drop Java 7 support soon), but the exception processing could be adjusted

          Oleg Nenashev added a comment - I agree that UnsupportedClassVersionError is a right error to be thrown in such case. Jenkins project does not support Java 6 starting from 1.610 (and it will likely drop Java 7 support soon), but the exception processing could be adjusted

          Oleg Nenashev added a comment -

          Oleg Nenashev added a comment - Created https://github.com/jenkinsci/remoting/pull/238

          Code changed in jenkins
          User: Oleg Nenashev
          Path:
          core/src/main/java/hudson/Launcher.java
          core/src/main/java/hudson/model/Computer.java
          core/src/main/java/hudson/slaves/ChannelPinger.java
          core/src/main/java/hudson/slaves/SlaveComputer.java
          core/src/main/java/jenkins/FilePathFilter.java
          core/src/main/java/jenkins/slaves/StandardOutputSwapper.java
          pom.xml
          test/src/test/java/hudson/bugs/JnlpAccessWithSecuredHudsonTest.java
          test/src/test/java/jenkins/security/Security218CliTest.java
          http://jenkins-ci.org/commit/jenkins/cb3990a4d6094260bea4571e7079fd0e3949047f
          Log:
          Update to Remoting 3.15 and Cleanup issues in Channel#current() usages (#3145)

          Pulls in fixes for: JENKINS-48133, JENKINS-48055, JENKINS-37566, JENKINS-48309, JENKINS-47965, JENKINS-48130, JENKINS-37670, JENKINS-37566, JENKINS-46724

          This change also adds some missing null/closing channel checks in the core.
          In some cases the change prevents spawning threads if the channel is in the invalid state.

          SCM/JIRA link daemon added a comment - Code changed in jenkins User: Oleg Nenashev Path: core/src/main/java/hudson/Launcher.java core/src/main/java/hudson/model/Computer.java core/src/main/java/hudson/slaves/ChannelPinger.java core/src/main/java/hudson/slaves/SlaveComputer.java core/src/main/java/jenkins/FilePathFilter.java core/src/main/java/jenkins/slaves/StandardOutputSwapper.java pom.xml test/src/test/java/hudson/bugs/JnlpAccessWithSecuredHudsonTest.java test/src/test/java/jenkins/security/Security218CliTest.java http://jenkins-ci.org/commit/jenkins/cb3990a4d6094260bea4571e7079fd0e3949047f Log: Update to Remoting 3.15 and Cleanup issues in Channel#current() usages (#3145) Pulls in fixes for: JENKINS-48133 , JENKINS-48055 , JENKINS-37566 , JENKINS-48309 , JENKINS-47965 , JENKINS-48130 , JENKINS-37670 , JENKINS-37566 , JENKINS-46724 This change also adds some missing null/closing channel checks in the core. In some cases the change prevents spawning threads if the channel is in the invalid state.

          Oleg Nenashev added a comment -

          The change has been released in Remoting 3.15 and integrated towards Jenkins 2.98

          Oleg Nenashev added a comment - The change has been released in Remoting 3.15 and integrated towards Jenkins 2.98

            oleg_nenashev Oleg Nenashev
            maslen Thomas Maslen
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: