KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > test > classloader > test > DeadlockTests32


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.test.classloader.test;
23
24 import java.net.URL JavaDoc;
25 import java.io.File JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import org.jboss.logging.Logger;
30 import org.jboss.mx.loading.UnifiedLoaderRepository3;
31 import org.jboss.mx.loading.UnifiedClassLoader3;
32 import org.jboss.mx.loading.LoaderRepository;
33 import org.jboss.mx.loading.LoadMgr3;
34 import org.jboss.test.classloader.circularity.test.MyClassLoadingTask;
35 import org.jboss.test.util.ClassMover;
36
37
38 /** Additional deadlock scenario tests of the UnifiedClassLoader3
39
40      .....................................
41      : +-------+ +-------+ :
42      : | TestA | | TestA2| :
43      : +---+---+ +---+---+ :
44      '''''''''|'''''''''''''''''''|'''''''
45               | extends |
46           ''''|'''''' |
47     ......|.........|.............|.........
48     : +--+----+ +--+----+ +--+----+ :
49     : | TestB | | TestB3| | TestB2| :
50     : +-------+ +-------+ +-------+ :
51     :......................................:
52  
53  @author Frank.Gamerdinger@Sun.COM
54  @author Scott.Stark@jboss.org
55  @version $Revision: 37406 $
56  */

57 public class DeadlockTests32
58 {
59    private static Logger log = Logger.getLogger(DeadlockTests32.class);
60    private SyncEvent syncEvent = new SyncEvent();
61    private TestClassLoader loaders[];
62    private UnifiedLoaderRepository3 mainRep;
63    private TestClassLoader blockingLoader;
64    private String JavaDoc blockname;
65
66    /**
67       [starksm@banshee testsuite]$ jar -tf output/lib/dl-a.jar
68       org/jboss/test/classloader/test/abc/TestA.class
69       org/jboss/test/classloader/test/abc/TestA2.class
70       [starksm@banshee testsuite]$ jar -tf output/lib/dl-b.jar
71       org/jboss/test/classloader/test/abc/TestB.class
72       org/jboss/test/classloader/test/abc/TestB2.class
73       org/jboss/test/classloader/test/abc/TestB3.class
74     @param libDir
75     @throws Exception
76     */

77    public DeadlockTests32(File JavaDoc libDir) throws Exception JavaDoc
78    {
79       ClassLoader JavaDoc appCl = this.getClass().getClassLoader();
80       URL JavaDoc u1 = new File JavaDoc(libDir, "dl-a.jar").toURL();
81       URL JavaDoc u2 = new File JavaDoc(libDir, "dl-b.jar").toURL();
82       loaders = new TestClassLoader[2];
83       mainRep = new UnifiedLoaderRepository3();
84       loaders[0] = new TestClassLoader(u1, appCl, mainRep);
85       loaders[1] = new TestClassLoader(u2, appCl, mainRep);
86    }
87
88    /** Scenario:
89
90     Thread T1 Thread T2
91     classLoader 1 [a.jar] classLoader 2 [b.jar]
92     
93              . .
94     t0 ------------------------------------------------------------
95              | | loadClass(abc.TestB)
96              | |----+
97              | +----+ registered,
98              | |
99              | |----+
100              | +----+ wait in beforeTaskLoop
101     t1 ------------------------------------------------------------
102              | load abc.TestB2 |
103              | schedule abc.TestB2 --------->|
104              | |
105              |-----+ |
106              | | nextTask(WAIT_ON_EVENT) |
107              +-----+ |
108     t2 ------------------------------------------------------------
109              | | <--- release beforeTaskLoop lock
110     t3 ------------------------------------------------------------
111              | | loadClassLocally(abc.TestB2)
112              | |
113              | |
114              |<+---------- schedule abc.TestA -----|
115              | |-----+ nextTask
116              | | |
117              | +-----+
118              | |
119              | | loadClassLocally
120              |<+---------- schedule abc.TestA2-----| abc.TestB
121              | |
122              | |-----+
123              | | | nextTask
124              | +-----+ wait
125              | |
126     t4 -------------------- Dead-Lock ----------------------------
127     @throws Exception
128     */

129    public void testDeadLock() throws Exception JavaDoc
130    {
131       log.info("RUNNING: testDeadLock");
132       File JavaDoc TestAclass = ClassMover.move("org.jboss.test.classloader.test.abc.TestA");
133       File JavaDoc TestBclass = ClassMover.move("org.jboss.test.classloader.test.abc.TestB");
134       File JavaDoc TestB2class = ClassMover.move("org.jboss.test.classloader.test.abc.TestB2");
135
136       /* Indicate that CL2 will wait after acquring the UCL registration monitor
137       and that the class its loading is TestB
138       */

139       blockingLoader = loaders[1];
140       blockname = "org.jboss.test.classloader.test.abc.TestB";
141       ClassLoader JavaDoc cl1 = loaders[0];
142       ClassLoader JavaDoc cl2 = loaders[1];
143       Runner t2 = new Runner("T2", blockname, cl2);
144       ThreadList threads = new ThreadList();
145       threads.add(t2);
146
147       log.info("t0, Waiting for T2 to start");
148       t2.start();
149       Thread.sleep(2000);
150       log.info("t1, T2 should be waiting in beforeTaskLoop");
151
152       /* Load B2 through T1/CL1 which requires CL2 held by T2
153       */

154       Runner t1 = new Runner("T1", "org.jboss.test.classloader.test.abc.TestB2", cl1);
155       threads.add(t1);
156       log.info("t2, Waiting for T1 to start");
157       t1.start();
158       Thread.sleep(4000);
159       log.info("t3, Now releasing T2/CL2");
160       syncEvent.set();
161       log.info("t4, Waiting for T1, T2 to complete");
162       threads.waitAll();
163
164       ClassMover.restore(TestAclass);
165       ClassMover.restore(TestBclass);
166       ClassMover.restore(TestB2class);
167    }
168
169    /** Scenario:
170
171     Thread T1 Thread T2
172     classLoader 1 [a.jar] classLoader 2 [b.jar]
173     
174              . .
175     t0 ------------------------------------------------------------
176              | | loadClass(abc.TestB)
177              | |----+
178              | +----+ registered,
179              | |
180              | |----+
181              | +----+ wait in beforeTaskLoop
182     t1 ------------------------------------------------------------
183              | load abc.TestB3 |
184              | schedule abc.TestB3 --------->|
185              | |
186              |-----+ |
187              | | nextTask(WAIT_ON_EVENT) |
188              +-----+ |
189     t2 ------------------------------------------------------------
190              | | <--- release beforeTaskLoop lock
191     t3 ------------------------------------------------------------
192              | | loadClassLocally(abc.TestB3)
193              | |
194              | |
195              |<+---------- schedule abc.TestA -----|
196              | loadClassLocally(abc.TestA) |
197              |-----+ |
198              | | nextTask(WAIT_ON_EVENT) |
199              +-----+ |
200              | | loadClassLocally(abc.TestB)
201              | | CCE(abc.TestA)
202              | |
203              | |-----+
204              | | | nextTask
205              | +-----+ wait(WAIT_ON_EVENT)
206              | |
207     t4 -------------------- Dead-Lock ----------------------------
208     @throws Exception
209     */

210    public void testDeadLockAndCircularity() throws Exception JavaDoc
211    {
212       log.info("RUNNING: testDeadLockAndCircularity");
213       File JavaDoc TestAclass = ClassMover.move("org.jboss.test.classloader.test.abc.TestA");
214       File JavaDoc TestBclass = ClassMover.move("org.jboss.test.classloader.test.abc.TestB");
215       File JavaDoc TestB3class = ClassMover.move("org.jboss.test.classloader.test.abc.TestB3");
216
217       /* Indicate that CL2 will wait after acquring the UCL registration monitor
218       and that the class its loading is TestB
219       */

220       blockingLoader = loaders[1];
221       blockname = "org.jboss.test.classloader.test.abc.TestB";
222       ClassLoader JavaDoc cl1 = loaders[0];
223       ClassLoader JavaDoc cl2 = loaders[1];
224       Runner t2 = new Runner("T2", blockname, cl2);
225       ThreadList threads = new ThreadList();
226       threads.add(t2);
227       // Start t2 so that it blocks
228
log.info("t0, Waiting for T2 to start");
229       t2.start();
230       Thread.sleep(2000);
231       log.info("t1, T2 should be waiting in beforeTaskLoop");
232
233       Runner t1 = new Runner("T1", "org.jboss.test.classloader.test.abc.TestB3", cl1);
234       threads.add(t1);
235       log.info("t2, Waiting for T1 to start");
236       t1.start();
237       Thread.sleep(4000);
238       log.info("t3, Now releasing T2/CL2");
239       syncEvent.set();
240       threads.waitAll();
241
242       ClassMover.restore(TestAclass);
243       ClassMover.restore(TestBclass);
244       ClassMover.restore(TestB3class);
245    }
246
247
248    private class Runner extends Thread JavaDoc
249    {
250       private String JavaDoc clsname;
251       private ClassLoader JavaDoc loader;
252
253       public Runner(String JavaDoc name, String JavaDoc clsname, ClassLoader JavaDoc cl)
254       {
255          super(name);
256          this.clsname = clsname;
257          this.loader = cl;
258       }
259
260       private Throwable JavaDoc savedEx;
261
262       public Throwable JavaDoc getThrowable()
263       {
264          return savedEx;
265       }
266
267       public void showException()
268       {
269          if (savedEx != null)
270          {
271             log.error("Exception for: " + getName(), savedEx);
272          }
273       }
274
275       public void run()
276       {
277          try
278          {
279             Class JavaDoc cls = Class.forName(clsname, true, loader);
280             cls.newInstance();
281          }
282          catch (Throwable JavaDoc ex)
283          {
284             savedEx = ex;
285          }
286       }
287
288    }
289
290
291    public void beforeTaskLoop(UnifiedClassLoader3 cl, String JavaDoc clsname)
292    {
293       log.info("BeforeTaskLoop: " + clsname);
294       if (cl == blockingLoader && clsname.equals(blockname))
295       {
296          log.info("Waiting in beforeTaskLoop: " + cl + " on " + blockname);
297          try
298          {
299             syncEvent.aquire();
300          }
301          catch (InterruptedException JavaDoc e)
302          {
303             log.error("Interrupted", e);
304          }
305          log.info("End beforeTaskLoop: " + cl);
306       }
307    }
308
309    public class TestClassLoader extends UnifiedClassLoader3
310    {
311       public TestClassLoader(URL JavaDoc url, ClassLoader JavaDoc parent,
312          LoaderRepository repository)
313       {
314          super(url, null, parent, null);
315          repository.addClassLoader(this);
316       }
317
318       public synchronized Class JavaDoc loadClassImpl(String JavaDoc name, boolean resolve)
319          throws ClassNotFoundException JavaDoc
320       {
321          boolean trace = log.isTraceEnabled();
322
323          /* Since loadClass can be called from loadClassInternal with the monitor
324             already held, we need to determine if there is a ClassLoadingTask
325             which requires this UCL. If there is, we release the UCL monitor
326             so that the ClassLoadingTask can use the UCL.
327           */

328          boolean acquired = attempt(1);
329          while( acquired == false )
330          {
331             /* Another thread needs this UCL to load a class so release the
332              monitor acquired by the synchronized method. We loop until
333              we can acquire the class loading lock.
334             */

335            try
336             {
337                if( trace )
338                   log.trace("Waiting for loadClass lock");
339                this.wait();
340             }
341             catch(InterruptedException JavaDoc ignore)
342             {
343             }
344             acquired = attempt(1);
345          }
346
347          MyClassLoadingTask task = null;
348          try
349          {
350             Thread JavaDoc t = Thread.currentThread();
351             // Register this thread as owning this UCL
352
if( loadLock.holds() == 1 )
353                LoadMgr3.registerLoaderThread(this, t);
354             // Callout to cause blocking with UCL monitor held
355
beforeTaskLoop(name);
356
357             // Create a class loading task and submit it to the repository
358
task = new MyClassLoadingTask(name, this, t);
359             /* Process class loading tasks needing this UCL until our task has
360                been completed by the thread owning the required UCL(s).
361              */

362             UnifiedLoaderRepository3 ulr3 = (UnifiedLoaderRepository3) repository;
363             if( LoadMgr3.beginLoadTask(task, ulr3) == false )
364             {
365                while( task.threadTaskCount() != 0 )
366                {
367                   try
368                   {
369                      LoadMgr3.nextTask(t, task, ulr3);
370                   }
371                   catch(InterruptedException JavaDoc e)
372                   {
373                      // Abort the load or retry?
374
break;
375                   }
376                }
377             }
378          }
379          finally
380          {
381             // Unregister as the UCL owner to reschedule any remaining load tasks
382
if( loadLock.holds() == 1 )
383                LoadMgr3.endLoadTask(task);
384             // Notify any threads waiting to use this UCL
385
this.release();
386             this.notifyAll();
387          }
388
389          if( task.loadedClass() == null )
390          {
391             if( task.loadException() instanceof ClassNotFoundException JavaDoc )
392                throw (ClassNotFoundException JavaDoc) task.loadException();
393             else if( task.loadException() != null )
394             {
395                if( log.isTraceEnabled() )
396                   log.trace("Unexpected error during load of:"+name, task.loadException());
397                String JavaDoc msg = "Unexpected error during load of: "+name
398                   + ", msg="+task.loadException().getMessage();
399                throw new ClassNotFoundException JavaDoc(msg);
400             }
401             // Assert that loadedClass is not null
402
else
403                throw new IllegalStateException JavaDoc("ClassLoadingTask.loadedTask is null, name: "+name);
404          }
405
406          return task.loadedClass();
407       }
408
409       protected void beforeTaskLoop(String JavaDoc clsname)
410       {
411          log.info("Calling taskLoop");
412          DeadlockTests32.this.beforeTaskLoop(this, clsname);
413       }
414
415    }
416
417    private class ThreadList
418    {
419       List JavaDoc list = new ArrayList JavaDoc();
420
421       public ThreadList()
422       {
423       }
424
425
426       public void add(Thread JavaDoc t)
427       {
428          list.add(t);
429       }
430
431       public void waitAll() throws Exception JavaDoc
432       {
433          Iterator JavaDoc it = list.iterator();
434          Throwable JavaDoc ex = null;
435          StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
436          while (it.hasNext())
437          {
438             Runner t = (Runner) it.next();
439             t.join();
440             //t.showException();
441
Throwable JavaDoc e = t.getThrowable();
442             if (e != null)
443             {
444                buf.append("Failure for: ").append(t.getName());
445                buf.append('\n').append(e);
446                if (ex == null)
447                {
448                   ex = e;
449                }
450             }
451          }
452          if (ex != null)
453          {
454             log.info(buf.toString());
455             if (ex instanceof Exception JavaDoc)
456             {
457                throw (Exception JavaDoc) ex;
458             }
459             else if (ex instanceof Error JavaDoc)
460             {
461                throw (Error JavaDoc) ex;
462             }
463          }
464       }
465
466    }
467
468    private class SyncEvent
469    {
470       private boolean cond;
471
472       public SyncEvent()
473       {
474          this(false);
475       }
476
477       public SyncEvent(boolean initialValue)
478       {
479          cond = initialValue;
480       }
481
482
483       public void aquire() throws InterruptedException JavaDoc
484       {
485          synchronized (this)
486          {
487             while (!cond)
488             {
489                wait();
490             }
491          }
492       }
493
494       public synchronized void set()
495       {
496          cond = true;
497          notifyAll();
498       }
499
500       public synchronized void unset()
501       {
502          cond = false;
503       }
504
505    }
506 }
507
Popular Tags