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

j:getStatic/invokeStatic does not work on plugin classes

    Details

    • Similar Issues:

      Description

      If in j:getStatic or j:invokeStatic you specify a className which is in a plugin, then try to render the resulting Jelly view, you get

      java.lang.ClassNotFoundException: some.Class
      	at org.jenkinsci.maven.plugins.hpi.ServletApiOnlyClassLoader.findClass(ServletApiOnlyClassLoader.java:25)
      	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
      	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
      	at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:363)
      	at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:325)
      	at org.apache.commons.jelly.tags.core.GetStaticTag.doTag(GetStaticTag.java:106)
      

      Indeed GetStaticTag does

      Class type = ClassLoaderUtils.getClassLoader(getClass()).loadClass(className);
      

      which calls

      public static ClassLoader getClassLoader(Class clazz) {
          ClassLoader callersLoader = clazz.getClassLoader();
          if (callersLoader == null) {
              callersLoader = ClassLoader.getSystemClassLoader();
          }
          return callersLoader;
      }
      

      so there is no way this could work.

      Workaround:

      ${app.pluginManager.uberClassLoader.loadClass('some.Class').getField('field').get(null)}
      ${app.pluginManager.uberClassLoader.loadClass('pkg.SomeExtension').getMethod('all', null).invoke(null, null)}
      

        Attachments

          Issue Links

            Activity

            Hide
            jglick Jesse Glick added a comment -

            JENKINS-31203 would obviate this sort of problem and make rendering more easily debugged.

            Show
            jglick Jesse Glick added a comment - JENKINS-31203 would obviate this sort of problem and make rendering more easily debugged.
            Hide
            jglick Jesse Glick added a comment -

            Also cf. JENKINS-41827 for mismatches between production and JenkinsRule testing.

            Show
            jglick Jesse Glick added a comment - Also cf.  JENKINS-41827 for mismatches between production and JenkinsRule testing.
            Hide
            jglick Jesse Glick added a comment -

            so while I haven't verified whether we set context classloader

            AFAICT we do not set Thread.contextClassLoader to UberClassLoader; currently it is WebAppClassLoader. Would be helpful for some purposes, but risky.

            Show
            jglick Jesse Glick added a comment - so while I haven't verified whether we set context classloader AFAICT we do not set Thread.contextClassLoader to UberClassLoader ; currently it is WebAppClassLoader . Would be helpful for some purposes, but risky.
            Hide
            jglick Jesse Glick added a comment -

            Similar problem seems to have hit Sam Van Oort when (unnecessarily) using the class argument to st:include and specifying a String argument: worked during hpi:run but not in production mode. (Using a Class argument does work.)

            Show
            jglick Jesse Glick added a comment - Similar problem seems to have hit Sam Van Oort when (unnecessarily) using the class argument to  st:include  and specifying a String argument: worked during hpi:run but not in production mode. (Using a Class argument does work .)
            Hide
            kohsuke Kohsuke Kawaguchi added a comment -

            In the version of commons-jelly that we use in the core (org.jenkins-ci:commons-jelly:jar:1.1-jenkins-20120928), the loadClass method looks like this:

                /**
                 * Loads the given class using the current Thread's context class loader first
                 * otherwise use the class loader which loaded this class.
                 */
                public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException {
                    ClassLoader loader = Thread.currentThread().getContextClassLoader();
                    if (loader == null) {
                        return getClassLoader(callingClass).loadClass(className);
                    } else {
                        return loader.loadClass(className);
                    }
                }
            

            ... so while I haven't verified whether we set context classloader, it seems like we've made an attempt to get this done correctly.

            Show
            kohsuke Kohsuke Kawaguchi added a comment - In the version of commons-jelly that we use in the core (org.jenkins-ci:commons-jelly:jar:1.1-jenkins-20120928), the loadClass method looks like this: /** * Loads the given class using the current Thread 's context class loader first * otherwise use the class loader which loaded this class. */ public static Class loadClass( String className, Class callingClass) throws ClassNotFoundException { ClassLoader loader = Thread .currentThread().getContextClassLoader(); if (loader == null ) { return getClassLoader(callingClass).loadClass(className); } else { return loader.loadClass(className); } } ... so while I haven't verified whether we set context classloader, it seems like we've made an attempt to get this done correctly.
            Hide
            jglick Jesse Glick added a comment -

            Other workarounds:

            • Use a Groovy view.
            • Avoid static calls by arranging to pass in an instance of this or a related class (for example as it) so you can make instance calls.
            Show
            jglick Jesse Glick added a comment - Other workarounds: Use a Groovy view. Avoid static calls by arranging to pass in an instance of this or a related class (for example as it ) so you can make instance calls.

              People

              • Assignee:
                Unassigned
                Reporter:
                jglick Jesse Glick
              • Votes:
                1 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated: