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

Plugins with optional dependencies and compiled with Java6 cause Exception in loading

    • Icon: Bug Bug
    • Resolution: Not A Defect
    • Icon: Major Major
    • core
    • None
    • Jenkins 1.532, 1.549
      Copy Artifact 1.28

      Steps to produce the problem:

      1. Install Copy Artifact
      2. Disable Maven plugin
      3. Restart Jenkins
      4. Fails to load Copy Artifact with: (full stacktrace is attached)
        1) Error injecting constructor, java.lang.NoClassDefFoundError: hudson/maven/MavenBuild
          at hudson.plugins.copyartifact.CopyArtifact$DescriptorImpl.<init>(Unknown Source)
        

      I found followings:

      • This can be reproduced when I package Copy Artifact with jdk 1.6.
      • This cannot be reproduced when I package Copy Artifact with jdk 1.7.

      It seems that something strange happens in Jenkins plugin loading system.
      It may be a problem with guice 4.0 introduced in aea10298 (may be guice does not work with Java1.6).

      What I will do are:

      • Create a minimum plugin to reproduce the problem.
      • Test what happens if reverted aea10298.
      • Test what happens if downgrade guice to guice 3.0 (fails to compile?)

          [JENKINS-21664] Plugins with optional dependencies and compiled with Java6 cause Exception in loading

          ikedam added a comment -

          when depending on maven-plugin...

          JDK Jenkins 1.523 1.524
          1.6   reproduce
          1.7    

          when depending on an original plugin...

          JDK Jenkins 1.523 1.524
          1.6 reproduce reproduce
          1.7    

          It seems nothing to do with guice...

          ikedam added a comment - when depending on maven-plugin... JDK Jenkins 1.523 1.524 1.6   reproduce 1.7     when depending on an original plugin... JDK Jenkins 1.523 1.524 1.6 reproduce reproduce 1.7     It seems nothing to do with guice...

          ikedam added a comment -

          Hmm... that difference seems caused by a6926e1c51c0650a48dec68cbe402248742dd55c.
          Installed, but disabled plugins are registered to class loaders in Jenkins < 1.524.

          ikedam added a comment - Hmm... that difference seems caused by a6926e1c51c0650a48dec68cbe402248742dd55c . Installed, but disabled plugins are registered to class loaders in Jenkins < 1.524.

          ikedam added a comment -

          This problem seems caused for Class#getMethod("getDescriptor") in Descriptor#<init> tries to load classes in optional depended plugins.
          It must be a problem with JDK.

          I'm not sure why but I cannot reproduce this behavior without Jenkins.

          ikedam added a comment - This problem seems caused for Class#getMethod("getDescriptor") in Descriptor#<init> tries to load classes in optional depended plugins. It must be a problem with JDK. I'm not sure why but I cannot reproduce this behavior without Jenkins.

          ikedam added a comment -

          I finally found the root cause.
          Upcasting in codes cause class loading:

          public void doSomething()
          {
            if(Jenkins.getInstance().getPlugin("dependee"))
            {
              Derived d = somemethod();
              Base b = (Derive)d; // <- This causes load Derive even not executing doSomething().
            }
          }
          

          and in Java6,

          for(Base b: getDerivedList())
          {
            someMethodForBase(b);
          }
          

          This code is compiled as following:

          for(Derived b: getDerivedList()) // <- Base is changed to Derived
          {
            someMethodForBase(b); // Here causes upcasting.
          }
          

          There are some exceptions:

          • Upcasting to Object does not cause class loading.
          • Conversion between generic types does not cause class loading. (as generic types are completely ignored in execution time)
            • Base b = derivedList.get( i ); does not cause class loading.
            • Base b = derivedIterator.next(); does not cause class loading.

          ikedam added a comment - I finally found the root cause. Upcasting in codes cause class loading: public void doSomething() { if (Jenkins.getInstance().getPlugin( "dependee" )) { Derived d = somemethod(); Base b = (Derive)d; // <- This causes load Derive even not executing doSomething(). } } and in Java6, for (Base b: getDerivedList()) { someMethodForBase(b); } This code is compiled as following: for (Derived b: getDerivedList()) // <- Base is changed to Derived { someMethodForBase(b); // Here causes upcasting. } There are some exceptions: Upcasting to Object does not cause class loading. Conversion between generic types does not cause class loading. (as generic types are completely ignored in execution time) Base b = derivedList.get( i ); does not cause class loading. Base b = derivedIterator.next(); does not cause class loading.

          ikedam added a comment -

          This is not a issue with Jenkins, but Java language feature.
          I wrote a tips note for this problem:
          https://wiki.jenkins-ci.org/display/JENKINS/Tips+for+optional+dependencies

          ikedam added a comment - This is not a issue with Jenkins, but Java language feature. I wrote a tips note for this problem: https://wiki.jenkins-ci.org/display/JENKINS/Tips+for+optional+dependencies

            ikedam ikedam
            ikedam ikedam
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: