1 /*
   2  * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.lang.instrument.*;
  25 import java.net.*;
  26 import java.io.*;
  27 import java.security.*;
  28 
  29 /**
  30  *      Test Java Agent
  31  *
  32  *      @author Daryl Puryear
  33  *      @copyright 1999-2004 Wily Technology, Inc.  All rights reserved.
  34  */
  35 public class ParallelTransformerLoaderAgent
  36 {
  37         private static URL sURL;
  38         private static ClassLoader sClassLoader;
  39 
  40         public static synchronized ClassLoader
  41         getClassLoader()
  42         {
  43                 return sClassLoader;
  44         }
  45 
  46         public static synchronized void
  47         generateNewClassLoader()
  48         {
  49                 sClassLoader = new URLClassLoader(new URL[] {sURL});
  50         }
  51 
  52         public static void
  53         premain(        String agentArgs,
  54                         Instrumentation instrumentation)
  55                 throws Exception
  56         {
  57                 if (agentArgs == null || agentArgs == "")
  58                 {
  59                         System.err.println("Error: No jar file name provided, test will not run.");
  60                         return;
  61                 }
  62 
  63                 sURL = (new File(agentArgs)).toURL();
  64                 System.out.println("Using jar file: " + sURL);
  65                 generateNewClassLoader();
  66 
  67                 instrumentation.addTransformer(new TestTransformer());
  68         }
  69 
  70         private static class TestTransformer
  71                 implements ClassFileTransformer
  72         {
  73                 public byte[]
  74                 transform(      ClassLoader loader,
  75                                 String className,
  76                                 Class classBeingRedefined,
  77                                 ProtectionDomain protectionDomain,
  78                                 byte[] classfileBuffer)
  79                         throws IllegalClassFormatException
  80                 {
  81                         String tName = Thread.currentThread().getName();
  82                         // In 160_03 and older, transform() is called
  83                         // with the "system_loader_lock" held and that
  84                         // prevents the bootstrap class loaded from
  85                         // running in parallel. If we add a slight sleep
  86                         // delay here when the transform() call is not
  87                         // main or TestThread, then the deadlock in
  88                         // 160_03 and older is much more reproducible.
  89                         if (!tName.equals("main") && !tName.equals("TestThread")) {
  90                             System.out.println("Thread '" + tName +
  91                                 "' has called transform()");
  92                             try {
  93                                 Thread.sleep(500);
  94                             } catch (InterruptedException ie) {
  95                             }
  96                         }
  97 
  98                         // load additional classes when called from other threads
  99                         // with system class loader. If we use the same class loader as
 100                         // in other thread, it will throw CircularityError since
 101                         // this loading is in middle of loading TestClass2 and cause
 102                         // CircularityError for JarLoader$2 which is put in placeholder
 103                         // but not loaded yet. We see it twice on stack, Detail see
 104                         // bug 8038468
 105                         if (!tName.equals("main"))
 106                         {
 107                                 loadClasses(3);
 108                         }
 109                         return null;
 110                 }
 111 
 112                 public static void
 113                 loadClasses( int index)
 114                 {
 115                         // ClassLoader loader = ParallelTransformerLoaderAgent.getClassLoader();
 116                         try
 117                         {
 118                                 //Class.forName("TestClass" + index, true, loader);
 119                                 Class.forName("TestClass" + index, true, ClassLoader.getSystemClassLoader());
 120                         }
 121                         catch (Exception e)
 122                         {
 123                                 e.printStackTrace();
 124                         }
 125                 }
 126         }
 127 }