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

Remoting does not retrieve resources in locally pre-fetched JARs

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • core, remoting
    • None

      Hudson remoting does not retrieve resources in locally pre-fetched JARs. Though this is a minor performance issue, it causes some Java APIs to break.

      For example, a Java API used in a Callable might expect that certain resources exist in the same JAR. So, to make the API happy, the Callable will use the PreloadJarTask to get the JAR pre-loaded on the client. With the current Hudson remoting, each resource retrieval causes the resource to be copied to a local file without considering whether it resides in a pre-loaded JAR.

      Consider a callable that uses the Java API called ReallyCool. Assume ReallyCool has a method named execute and we've pre-loaded all JARs containing logo.png:

      01: public static void execute() {
      02:
      03:    // This call will cause every resource with the name logo.png
      04:    // to be downloaded from the server and stored as a local
      05:    // file. This should be fixed so that it first checks if any
      06:    // of the pre-loaded JARs have the resource before downloading
      07:    // them from the server.
      08:
      09:    Enumeration<URL> logo = classLoader.getResources("logo.png");
      10:
      11:    while (logo.hasMoreElements()) {
      12:        String urlspec = logo.nextElement().toExternalForm();
      13:        urlspec = urlspec.replace("logo.png", "META-INF/MANIFEST.MF");
      14:        URL manifest = new URL(urlspec);
      15:        InputStream stream manifest.openStream();
      16:        // Oh, no: stream is null since the URL isn't alongside
      17:        // logo in the same directory.
      18:    }
      19: }
      

      With the current implementation, the following will happen.

      In line 12, logo's URL will be something like: jar:file:/tmp/hudson-remoting1234/logo.png. This is because the RemoteClassLoader findResources() method always downloads resources from the server without considering the pre-loaded JARs.

      When the manifest URL is created in lines 13-15, it will be: jar:file:/tmp/hudson-remoting1234/META-INF/MANIFEST.MF. When we attempt to open a stream on it, the stream will be null since that file does not exist.

      However, since we pre-loaded it, we expect the lookups of logo.png in line 12 to be like: jar:file:/tmp/hudson-remoting5678/important.jar!/logo.png. Then, the code above that looks up the manifest file in lines 13-15 will work properly since important.jar will exist locally.

      I provided a unit test, RemoteClassLoaderTest, that tests this functionality and illustrates the failure.

        1. RemoteClassLoader.diff
          72 kB
          frankjacobs
        2. RemoteClassLoader.diff
          71 kB
          frankjacobs
        3. RemoteClassLoaderTest.java
          13 kB
          frankjacobs

            Unassigned Unassigned
            frankjacobs frankjacobs
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: