hotspot/test/compiler/jsr292/ConcurrentClassLoadingTest.java
changeset 19713 8ef23b417f55
child 21729 6fe1dafeb82e
equal deleted inserted replaced
19712:b0bdff06b6fb 19713:8ef23b417f55
       
     1 /*
       
     2  * Copyright (c) 2013, 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 /**
       
    25  * @test
       
    26  * @bug 8022595
       
    27  * @summary JSR292: deadlock during class loading of MethodHandles, MethodHandleImpl & MethodHandleNatives
       
    28  *
       
    29  * @run main/othervm ConcurrentClassLoadingTest
       
    30  */
       
    31 import java.util.*;
       
    32 import java.util.concurrent.BrokenBarrierException;
       
    33 import java.util.concurrent.CyclicBarrier;
       
    34 
       
    35 public class ConcurrentClassLoadingTest {
       
    36     int numThreads = 0;
       
    37     long seed = 0;
       
    38     CyclicBarrier l;
       
    39     Random rand;
       
    40 
       
    41     public static void main(String[] args) throws Throwable {
       
    42         ConcurrentClassLoadingTest test = new ConcurrentClassLoadingTest();
       
    43         test.parseArgs(args);
       
    44         test.run();
       
    45     }
       
    46 
       
    47     void parseArgs(String[] args) {
       
    48         int i = 0;
       
    49         while (i < args.length) {
       
    50             String flag = args[i];
       
    51             switch(flag) {
       
    52                 case "-seed":
       
    53                     seed = Long.parseLong(args[++i]);
       
    54                     break;
       
    55                 case "-numThreads":
       
    56                     numThreads = Integer.parseInt(args[++i]);
       
    57                     break;
       
    58                 default:
       
    59                     throw new Error("Unknown flag: " + flag);
       
    60             }
       
    61             ++i;
       
    62         }
       
    63     }
       
    64 
       
    65     void init() {
       
    66         if (numThreads == 0) {
       
    67             numThreads = Runtime.getRuntime().availableProcessors();
       
    68         }
       
    69 
       
    70         if (seed == 0) {
       
    71             seed = (new Random()).nextLong();
       
    72         }
       
    73         rand = new Random(seed);
       
    74 
       
    75         l = new CyclicBarrier(numThreads + 1);
       
    76 
       
    77         System.out.printf("Threads: %d\n", numThreads);
       
    78         System.out.printf("Seed: %d\n", seed);
       
    79     }
       
    80 
       
    81     final List<Loader> loaders = new ArrayList<>();
       
    82 
       
    83     void prepare() {
       
    84         List<String> c = new ArrayList<>(Arrays.asList(classNames));
       
    85 
       
    86         // Split classes between loading threads
       
    87         int count = (classNames.length / numThreads) + 1;
       
    88         for (int t = 0; t < numThreads; t++) {
       
    89             List<String> sel = new ArrayList<>();
       
    90 
       
    91             System.out.printf("Thread #%d:\n", t);
       
    92             for (int i = 0; i < count; i++) {
       
    93                 if (c.size() == 0) break;
       
    94 
       
    95                 int k = rand.nextInt(c.size());
       
    96                 String elem = c.remove(k);
       
    97                 sel.add(elem);
       
    98                 System.out.printf("\t%s\n", elem);
       
    99             }
       
   100             loaders.add(new Loader(sel));
       
   101         }
       
   102 
       
   103         // Print diagnostic info when the test hangs
       
   104         Runtime.getRuntime().addShutdownHook(new Thread() {
       
   105             public void run() {
       
   106                 boolean alive = false;
       
   107                 for (Loader l : loaders) {
       
   108                     if (!l.isAlive())  continue;
       
   109 
       
   110                     if (!alive) {
       
   111                         System.out.println("Some threads are still alive:");
       
   112                         alive = true;
       
   113                     }
       
   114 
       
   115                     System.out.println(l.getName());
       
   116                     for (StackTraceElement elem : l.getStackTrace()) {
       
   117                         System.out.println("\t"+elem.toString());
       
   118                     }
       
   119                 }
       
   120             }
       
   121         });
       
   122     }
       
   123 
       
   124     public void run() throws Throwable {
       
   125         init();
       
   126         prepare();
       
   127 
       
   128         for (Loader loader : loaders) {
       
   129             loader.start();
       
   130         }
       
   131 
       
   132         l.await();
       
   133 
       
   134         for (Loader loader : loaders) {
       
   135             loader.join();
       
   136         }
       
   137     }
       
   138 
       
   139     class Loader extends Thread {
       
   140         List<String> classes;
       
   141 
       
   142         public Loader(List<String> classes) {
       
   143             this.classes = classes;
       
   144             setDaemon(true);
       
   145         }
       
   146 
       
   147         @Override
       
   148         public void run() {
       
   149             try {
       
   150                 l.await();
       
   151 
       
   152                 for (String name : classes) {
       
   153                     Class.forName(name).getName();
       
   154                 }
       
   155             } catch (ClassNotFoundException | BrokenBarrierException | InterruptedException e) {
       
   156                 throw new Error(e);
       
   157             }
       
   158         }
       
   159     }
       
   160 
       
   161     final static String[] classNames = {
       
   162             "java.lang.invoke.AbstractValidatingLambdaMetafactory",
       
   163             "java.lang.invoke.BoundMethodHandle",
       
   164             "java.lang.invoke.CallSite",
       
   165             "java.lang.invoke.ConstantCallSite",
       
   166             "java.lang.invoke.DirectMethodHandle",
       
   167             "java.lang.invoke.InnerClassLambdaMetafactory",
       
   168             "java.lang.invoke.InvokeDynamic",
       
   169             "java.lang.invoke.InvokeGeneric",
       
   170             "java.lang.invoke.InvokerBytecodeGenerator",
       
   171             "java.lang.invoke.Invokers",
       
   172             "java.lang.invoke.LambdaConversionException",
       
   173             "java.lang.invoke.LambdaForm",
       
   174             "java.lang.invoke.LambdaMetafactory",
       
   175             "java.lang.invoke.MagicLambdaImpl",
       
   176             "java.lang.invoke.MemberName",
       
   177             "java.lang.invoke.MethodHandle",
       
   178             "java.lang.invoke.MethodHandleImpl",
       
   179             "java.lang.invoke.MethodHandleInfo",
       
   180             "java.lang.invoke.MethodHandleNatives",
       
   181             "java.lang.invoke.MethodHandleProxies",
       
   182             "java.lang.invoke.MethodHandles",
       
   183             "java.lang.invoke.MethodHandleStatics",
       
   184             "java.lang.invoke.MethodType",
       
   185             "java.lang.invoke.MethodTypeForm",
       
   186             "java.lang.invoke.MutableCallSite",
       
   187             "java.lang.invoke.SerializedLambda",
       
   188             "java.lang.invoke.SimpleMethodHandle",
       
   189             "java.lang.invoke.SwitchPoint",
       
   190             "java.lang.invoke.TypeConvertingMethodAdapter",
       
   191             "java.lang.invoke.VolatileCallSite",
       
   192             "java.lang.invoke.WrongMethodTypeException"
       
   193     };
       
   194 }