ClassLoading locked when loading class by two threads.
program hanged, the thread stack below shows that it seems that jvm locked when loading class by 2 threads.
The jdk is jdk1.4.2_11.Is this a jdk bug?
the detail stack follows:
"RMI TCP Connection(2782)-10.40.79.5" daemon prio=5 tid=0x05551678 nid=0x114b in
Object.wait() [0xae4fd000..0xae5019c0]
at org.jboss.util.NestedThrowable.<clinit>(NestedThrowable.java:39)
at org.jboss.resource.connectionmanager.JBossLocalXAException.printStack
Trace(JBossLocalXAException.java:97)
at org.apache.log4j.spi.ThrowableInformation.getThrowableStrRep(Throwabl
eInformation.java:50)
at org.apache.log4j.spi.LoggingEvent.getThrowableStrRep(LoggingEvent.jav
a:333)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:295)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:150)
"RMI TCP Connection(2768)-10.40.79.5" daemon prio=5 tid=0x028c7a08 nid=0x113d in
Object.wait() [0xaf2fd000..0xaf3019c0]
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:141)
at org.jboss.util.NestedThrowable$1.class$(NestedThrowable.java:101)
at org.jboss.util.NestedThrowable$Util.<clinit>(NestedThrowable.java:101
)
at org.jboss.resource.ResourceException.getMessage(ResourceException.jav
a:113)
at org.jboss.util.NestedSQLException.<init>(NestedSQLException.java:62)
source code follows:
/***************************************
* *
* JBoss: The OpenSource J2EE WebOS*
* *
* Distributable under LGPL license. *
* See terms of license at gnu.org.*
* *
***************************************/
package org.jboss.util;
import java.io.PrintWriter;
import java.io.PrintStream;
import java.io.Serializable;
import org.jboss.logging.Logger;
import org.jboss.util.platform.Java;
/**
* Interface which is implemented by all the nested throwable flavors.
*
* @version <tt>$Revision: 1.2.2.4 $</tt>
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
*/
public interface NestedThrowable
extends Serializable
{
/**
* A system wide flag to enable or disable printing of the
* parent throwable traces.
*
*
* This value is set from the system property
* <tt>org.jboss.util.NestedThrowable.parentTraceEnabled</tt>
* or if that is not set defaults to <tt>true</tt>.
*/
boolean PARENT_TRACE_ENABLED = Util.getBoolean("parentTraceEnabled", true);
/**
* A system wide flag to enable or disable printing of the
* nested detail throwable traces.
*
*
* This value is set from the system property
* <tt>org.jboss.util.NestedThrowable.nestedTraceEnabled</tt>
* or if that is not set defaults to <tt>true</tt> unless
* using JDK 1.4 with {@link #PARENT_TRACE_ENABLED} set to false,
* then <tt>false</tt> since there is a native mechansim for this there.
*
*
* Note then when running under 1.4 is is not possible to disable
* the nested trace output, since that is handled by java.lang.Throwable
* which we delegate the parent printing to.
*/
boolean NESTED_TRACE_ENABLED = Util.getBoolean("nestedTraceEnabled",
(Java.isCompatible(Java.VERSION_1_4) &&
!PARENT_TRACE_ENABLED) ||
!Java.isCompatible(Java.VERSION_1_4));
/**
* A system wide flag to enable or disable checking of parent and child
* types to detect uneeded nesting
*
*
* This value is set from the system property
* <tt>org.jboss.util.NestedThrowable.detectDuplicateNesting</tt>
* or if that is not set defaults to <tt>true</tt>.
*/
boolean DETECT_DUPLICATE_NESTING = Util.getBoolean("detectDuplicateNesting", true);
/**
* Return the nested throwable.
*
* @return Nested throwable.
*/
Throwable getNested();
/**
* Return the nested <tt>Throwable</tt>.
*
*
For JDK 1.4 compatibility.
*
* @return Nested <tt>Throwable</tt>.
*/
Throwable getCause();
/////////////////////////////////////////////////////////////////////////
// Nested Throwable Utilities //
/////////////////////////////////////////////////////////////////////////
/**
* Utilitiy methods for the various flavors of
* <code>NestedThrowable</code>.
*/
final class Util
{
// Can not be final due to init bug, see getLogger() for details
private static Logger log = Logger.getLogger(NestedThrowable.class);
/**
* Something is very broken with class nesting, which can sometimes
* leave log uninitialized durring one of the following method calls.
*
*
* This is a HACK to keep those methods from NPE until this problem
* can be resolved.
*/
private static Logger getLogger()
{
if (log == null)
log = Logger.getLogger(NestedThrowable.class);
return log;
}
/** A helper to get a boolean property. */
protected static boolean getBoolean(String name, boolean defaultValue)
{
name = NestedThrowable.class.getName() + "." + name;
String value = System.getProperty(name, String.valueOf(defaultValue));
// HACK see getLogger() for details
log = getLogger();
log.debug(name + "=" + value);
return new Boolean(value).booleanValue();
}
/**
* Check and possibly warn if the nested exception type is the same
* as the parent type (duplicate nesting).
*/
public static void checkNested(final NestedThrowable parent,
final Throwable child)
{
if (!DETECT_DUPLICATE_NESTING || parent == null || child == null) return;
Class parentType = parent.getClass();
Class childType = child.getClass();
//
// This might be backwards... I always get this confused
//
if (parentType.isAssignableFrom(childType)) {
// HACK see getLogger() for details
log = getLogger();
// by quanrui 20050404
//log.warn("Duplicate throwable nesting of same base type: " + parentType + " is assignable from: " + childType);
log.debug("Duplicate throwable nesting of same base type: " + parentType + " is assignable from: " + childType);
}
}
/**
* Returns a formated message for the given detail message
* and nested <code>Throwable</code>.
*
* @param msgDetail message.
* @param nested Nested <code>Throwable</code>.
* @returnFormatted message.
*/
public static String getMessage(final String msg,
final Throwable nested)
{
StringBuffer buff = new StringBuffer(msg == null ? "" : msg);
if (nested != null) {
buff.append(msg == null ? "- " : "; - ")
.append("nested throwable: (")
.append(nested)
.append(")");
}
return buff.toString();
}
/**
* Prints the nested <code>Throwable</code> to the given stream.
*
* @param nested Nested <code>Throwable</code>.
* @param stream Stream to print to.
*/
public static void print(final Throwable nested,
final PrintStream stream)
{
if (stream == null)
throw new NullArgumentException("stream");
if (NestedThrowable.NESTED_TRACE_ENABLED && nested != null) {
synchronized (stream) {
if (NestedThrowable.PARENT_TRACE_ENABLED) {
stream.print(" + nested throwable: ");
}
else {
stream.print("[ parent trace omitted ]: ");
}
nested.printStackTrace(stream);
}
}
}
/**
* Prints the nested <code>Throwable</code> to the given writer.
*
* @param nested Nested <code>Throwable</code>.
* @param writer Writer to print to.
*/
public static void print(final Throwable nested,
final PrintWriter writer)
{
if (writer == null)
throw new NullArgumentException("writer");
if (NestedThrowable.NESTED_TRACE_ENABLED && nested != null) {
synchronized (writer) {
if (NestedThrowable.PARENT_TRACE_ENABLED) {
writer.print(" + nested throwable: ");
}
else {
writer.print("[ parent trace omitted ]: ");
}
nested.printStackTrace(writer);
}
}
}
}
}

