Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4267348

URLClassLoader is not threadsafe

XMLWordPrintable

    • kestrel
    • x86
    • windows_nt



      Name: tb29552 Date: 08/31/99


      /*

      Calling getResource on URLClassLoader is not threadsafe. Calling
      getResource from multiple threads results in jar file URLs being
      "dropped". This in turn can cause loadClass to throw
      NoClassDefFoundErrors because the jar file which contained the
      class was dropped due to data structure corruption.

      ClassLoader.getResource calls URLClassLoader.findResource which
      calls URLClassPath.getResource(String,boolean) which calls
      URLClassPath.getLoader(int). None of the above are synchronized.
      URLClassPath.getLoader(int) uses a java.util.HashMap and
      java.util.ArrayList both of which are not threadsafe.

      (the above applies to ClassLoader.getResources also)

      Multiple threads simultaneously in URLClassPath.getLoader(int)
      results in URLs being popped from URLClassPaths URL stack but not
      added to the list of Loaders. Therefore none of the resources or
      classes in the skipped URLs can be loaded.

      To duplicate the problem do the following:
      1) Create 6 text files each 4K in size. Name them res1.txt, res2.txt etc.
      2) jar each text file into its own jar file named res1.jar, res2.jar etc.
      3) Put the jar files on a web server
      4) Make sure your web server is configured to serve *.jar files.
      5) Run following program using a URL referring to the jar
         files you placed on the web server.

      When you run the program, on each run you will see some "loaded
      null" printouts. These represent jar files that were skipped by
      URLClassLoader due to corruption.

      */
      package RL;

      import java.net.*;
      public class ResourceLoader extends Object {
          String progName = null;
          String testURL = null;

          public ResourceLoader () {
      super();
      progName = this.getClass().getName();
          }

          private void showUsage() {
      System.err.print("usage:\n java -DtestURL=\"http://YourWebServer/\" " +
      progName + "\n");
      System.exit(0);
          }

          private void doWork(String[] args)
      throws Exception
          {

      testURL = java.lang.System.getProperty("testURL");
      if ((args.length != 0) || (testURL == null)) {
      showUsage();
      }
      final URLClassLoader cl = new URLClassLoader(
      new URL[] {
      new URL(testURL + "res6.jar"),
      new URL(testURL + "res1.jar"),
      new URL(testURL + "res2.jar"),
      new URL(testURL + "res4.jar"),
      new URL(testURL + "res3.jar"),
      new URL(testURL + "res5.jar"),
      });

      Thread thdRes1 = new Thread("Res1Loader") {
      public void run() {
      try {
      System.out.println("loading res1.txt");
      URL url = cl.getResource("res1.txt");
      System.out.println("loaded " + url);
      } catch(Exception e) {
      e.printStackTrace();
      }
      }
      };
      Thread thdRes2 = new Thread("Res2Loader") {
      public void run() {
      try {
      System.out.println("loading res2.txt");
      URL url = cl.getResource("res2.txt");
      System.out.println("loaded " + url);
      } catch(Exception e) {
      e.printStackTrace();
      }
      }
      };
      Thread thdRes3 = new Thread("Res3Loader") {
      public void run() {
      try {
      System.out.println("loading res3.txt");
      URL url = cl.getResource("res3.txt");
      System.out.println("loaded " + url);
      } catch(Exception e) {
      e.printStackTrace();
      }
      }
      };
      Thread thdRes4 = new Thread("Res4Loader") {
      public void run() {
      try {
      System.out.println("loading res4.txt");
      URL url = cl.getResource("res4.txt");
      System.out.println("loaded " + url);
      } catch(Exception e) {
      e.printStackTrace();
      }
      }
      };
      Thread thdRes5 = new Thread("Res5Loader") {
      public void run() {
      try {
      System.out.println("loading res5.txt");
      URL url = cl.getResource("res5.txt");
      System.out.println("loaded " + url);
      } catch(Exception e) {
      e.printStackTrace();
      }
      }
      };
      Thread thdRes6 = new Thread("Res6Loader") {
      public void run() {
      try {
      System.out.println("loading res6.txt");
      URL url = cl.getResource("res6.txt");
      System.out.println("loaded " + url);
      } catch(Exception e) {
      e.printStackTrace();
      }
      }
      };

      thdRes1.start();
      Thread.yield();
      thdRes2.start();
      Thread.yield();
      thdRes3.start();
      thdRes4.start();
      thdRes5.start();
      Thread.yield();
      thdRes6.start();
          }

          public static void main(String args[])
      throws Exception
          {
      ResourceLoader my = new ResourceLoader();
      my.doWork(args);
          }
      }

      (Review ID: 93936)
      ======================================================================

            zlisunw Zhenghua Li (Inactive)
            tbell Tim Bell
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: