📄 cltestconc.java
字号:
/* * Test for concurrency in ClassLoaders * * Note that this test needs a second public class which is in * CLTestConc_run.java * * This test tests that the VM can safely recover from threads stopping * while loading classes via loadClass. * * Written by Godmar Back <gback@cs.utah.edu> */import java.io.File;import java.io.FileInputStream;public class CLTestConc extends ClassLoader{ static boolean verbose = false; Thread first, second; /* * We first create one loader and load "CLTestConc_run". * Then we start three threads that attempt to create a new instance * of that class. CLTestConc_run references CLTestConc_bis. * * We must ensure several things. * First, we must ensure that the VM does not call out to a custom loader * while another call is in progress. * * Second, we must ensure that the VM attempts to * load a class after its first attempt failed because the thread * executing the loadClass method died. * * Third, we must ensure that a class is considered loaded (and all * threads waiting for it) are resumed as soon as the class has been * defined via defineClass. * * We use three threads, which can execute in arbitrary order. * Thread 1 is the first one trying to load the class. * We make it wait for 2 seconds and the die *before* calling defineClass. * Thread 2 is the second thread trying to load the class. * It loads the class's bytes and defines it via defineClass, but it * dies before it has a chance to return from loadClass. * Thread 3 just sits and waits until the class is loaded. Thread 3 * is unblocked as soon as thread 2 defines the class and returns * from loadClass (except, of course, it doesn't return---but loadClass * catches ThreadDeath) * * Thread 3, being the only one alive, will then move on to resolve * references of CLTestConc_bis to other classes. Once that happens, * we set its name to "Success", and because thread 3 is the only * surviving thread, this is all that's printed. */ protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Thread current = Thread.currentThread(); if (verbose) System.out.println(current + " asked to load " + name); if (name.equals("CLTestConc_bis")) { if (first == null) { if (verbose) System.out.println("first thread asked to load " + name); current.setName("Failure 1."); try { /* A wrong implementation might now send the other threads * in here. In this case, all will be stopped. */ wait(2000); } catch (InterruptedException _) { } first = current; if (verbose) System.out.println("stopping first thread"); // interestingly, JDK 1.2 doesn't throw a ThreadDeath when // I call stop here --- it just ignores it. current.stop(); if (verbose) System.out.println("first thread was not stopped???"); // this convinces even 1.2 that I want out. throw new ThreadDeath(); } else if (second == null) { if (verbose) System.out.println("second thread asked to load " + name); second = current; /* We will stop the second thread below. Like the first thread, * it is another unlucky candidate trying to load this class */ second.setName("Failure 2."); } else { if (verbose) System.out.println("third thread asked to load " + name); System.out.println("Failure 3."); System.exit(1); } } Class c = null; if (name.startsWith("CLTestConc")) { byte [] b = null; try { b = readin(name + ".class"); } catch (Exception e) { System.out.println(e); } c = defineClass(name, b, 0, b.length); /* The second thread dies after defining the class * This should unblock the third thread. */ if (current == second) { if (verbose) System.out.println("stopping second thread"); current.stop(); throw new ThreadDeath(); } } else { /* The third thread, loading stuff to which CLTestConc_* refers */ if (current != second && second != null) { current.setName("Success."); } if (verbose) System.out.println(current + " is calling findSystemClass"); c = findSystemClass(name); } if (resolve) resolveClass(c); return c; } /* * read a .class file */ static byte [] readin(String name) throws Exception { File cf = new File(name); FileInputStream cfi = new FileInputStream(cf); int len = (int)cf.length(); byte [] cb = new byte[len]; if (cfi.read(cb) != len) throw new Exception("short read for " + name); return cb; } static class CLTestConc_loader extends Thread { Class c; CLTestConc_loader(Class c) { this.c = c; } public void run() { try { Object o = c.newInstance(); System.out.println(o); } catch (Exception e) { e.printStackTrace(); } } } public static void main(String []av) throws Exception { verbose = av.length > 0; CLTestConc loader = new CLTestConc(); final Class c = loader.loadClass("CLTestConc_run", true); Thread t = new CLTestConc_loader(c); Thread t1 = new CLTestConc_loader(c); Thread t2 = new CLTestConc_loader(c); t.start(); t1.start(); t2.start(); t.join(); t1.join(); t2.join(); }}// javac flags: -nowarn// sources: CLTestConc_run.java/* Expected Output:Success.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -