-
Bug
-
Resolution: Fixed
-
P3
-
1.4.0, 1.4.2
-
b51
-
x86, sparc
-
windows, windows_2000
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2139628 | 5.0u8 | Karen Kinnear | P1 | Closed | Fixed | b01 |
Name: nt126004 Date: 06/10/2002
FULL PRODUCT VERSION :
java version "1.3.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24)
Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode)
and
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
A DESCRIPTION OF THE PROBLEM :
This problem happens both in JDK 1.3.1 and in 1.4.0,
Windows 2000.
When 2 threads are loading the same class with the same
classloader, and somehow one of the 2 threads releases the
synchronization lock on the classloader, the JVM code
throws ClassCircularityError, mistakenly.
Refer to the JVM class (in systemDictionary.cpp) and method
SystemDictionary::resolve_instance_class_or_null(...) for
where the bug is originating.
Refer also to RFE #4670071. As explained there, in JBoss
3.0 (http://www.jboss.org) a new classloading model is
used, not based on the tree model, that gives important
features such as hot-deploy and modularity. Because of the
synchronization on the classloader, JBoss' classloading
model (or any other classloading mechanism not based on the
tree model) may suffers of deadlocks. In JBoss 3.0 the
deadlock issue has been resolved, releasing the classloader
lock, but this solution showed up the ClassCircularityError
bug, this time in JVM code, and hence with no solution.
Probably the JVM code should throw ClassCircularityError if
a placeholder is found by the same thread that put it, not
if another thread is coming in asking for the same class
with the same classloader.
Note that the problem originates by calls that trigger a
call to the native code in
SystemDictionary::resolve_instance_class_or_null(...); from
investigation I was able to find these methods:
1. Class.defineClass
2. Class.loadClassInternal
3. Class.newInstance (and Constructor.newInstance)
4. Class.forName
There may be other, the code submitted only shows the
problem with 3., but in JBoss the problem is seen it with
all of the 4 cases listed above.
In the code submitted, URLClassLoader has been subclassed
only to make a reproducible test case, but in real code
there is no need to subclass it to get the problem (only
will happen only in certain situation/thread timing).
It would be nice that this bug and RFE #4670071 will go on
in parallell, to give more freedom to the classloading
mechanism.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Make 4 files of the submitted code, namely Base.java,
Derived.java, Support.java and Main.java.
2. Compile the files, for example in directory classes/
3. java -cp classes Main
EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected result: no errors, the 2 threads are able to load
the classes
Actual Result: ClassCircularityError is thrown.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.ClassCircularityError: Base
at Support.<init>(Support.java:7)
at java.lang.Class.newInstance0(Native Method)
at java.lang.Class.newInstance(Class.java:237)
at Main$Run1.run(Main.java:97)
at java.lang.Thread.run(Thread.java:484)
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Base {}
public class Derived extends Base {}
public class Support
{
private Base base = new Base();
}
import java.net.URL;
import java.net.URLClassLoader;
/**
*
* @version $Revision$
*/
public class Main
{
public static void main(String[] args) throws Exception
{
new Main();
}
private Object lock = new Object();
public Main() throws Exception
{
URL location = getClass().getProtectionDomain().getCodeSource
().getLocation();
URLLoader loader = new URLLoader(new URL[] {location}, getClass
().getClassLoader().getParent());
Class cls = loader.loadClass("Support");
Thread t1 = new Thread(new Run1(cls));
t1.start();
Thread.sleep(1000);
// Load Derived, will trigger a loadClassInternal for Base
loader.loadClass("Derived");
}
public class URLLoader extends URLClassLoader
{
private boolean m_firstTime = true;
public URLLoader(URL[] urls, ClassLoader parent)
{
super(urls, parent);
}
public Class loadClass(String name) throws ClassNotFoundException
{
if (name.equals("Base"))
{
if (m_firstTime)
{
m_firstTime = false;
// Notify the other thread
synchronized (lock)
{
lock.notifyAll();
}
// Wait on the classloader to have the JVM throw
ClassCircularityError
try
{
synchronized (this)
{
wait(5000);
}
}
catch (InterruptedException ignored)
{
}
}
}
return super.loadClass(name);
}
}
public class Run1 implements Runnable
{
private Class cls;
public Run1(Class cls)
{
this.cls = cls;
}
public void run()
{
synchronized (lock)
{
try
{
lock.wait();
}
catch (InterruptedException ignored) {}
}
// Trigger loadClassInternal for Base
try
{
cls.newInstance();
}
catch (Throwable x)
{
x.printStackTrace();
}
}
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
None, unfortunately.
(Review ID: 148304)
======================================================================
FULL PRODUCT VERSION :
java version "1.3.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24)
Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode)
and
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
A DESCRIPTION OF THE PROBLEM :
This problem happens both in JDK 1.3.1 and in 1.4.0,
Windows 2000.
When 2 threads are loading the same class with the same
classloader, and somehow one of the 2 threads releases the
synchronization lock on the classloader, the JVM code
throws ClassCircularityError, mistakenly.
Refer to the JVM class (in systemDictionary.cpp) and method
SystemDictionary::resolve_instance_class_or_null(...) for
where the bug is originating.
Refer also to RFE #4670071. As explained there, in JBoss
3.0 (http://www.jboss.org) a new classloading model is
used, not based on the tree model, that gives important
features such as hot-deploy and modularity. Because of the
synchronization on the classloader, JBoss' classloading
model (or any other classloading mechanism not based on the
tree model) may suffers of deadlocks. In JBoss 3.0 the
deadlock issue has been resolved, releasing the classloader
lock, but this solution showed up the ClassCircularityError
bug, this time in JVM code, and hence with no solution.
Probably the JVM code should throw ClassCircularityError if
a placeholder is found by the same thread that put it, not
if another thread is coming in asking for the same class
with the same classloader.
Note that the problem originates by calls that trigger a
call to the native code in
SystemDictionary::resolve_instance_class_or_null(...); from
investigation I was able to find these methods:
1. Class.defineClass
2. Class.loadClassInternal
3. Class.newInstance (and Constructor.newInstance)
4. Class.forName
There may be other, the code submitted only shows the
problem with 3., but in JBoss the problem is seen it with
all of the 4 cases listed above.
In the code submitted, URLClassLoader has been subclassed
only to make a reproducible test case, but in real code
there is no need to subclass it to get the problem (only
will happen only in certain situation/thread timing).
It would be nice that this bug and RFE #4670071 will go on
in parallell, to give more freedom to the classloading
mechanism.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Make 4 files of the submitted code, namely Base.java,
Derived.java, Support.java and Main.java.
2. Compile the files, for example in directory classes/
3. java -cp classes Main
EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected result: no errors, the 2 threads are able to load
the classes
Actual Result: ClassCircularityError is thrown.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.ClassCircularityError: Base
at Support.<init>(Support.java:7)
at java.lang.Class.newInstance0(Native Method)
at java.lang.Class.newInstance(Class.java:237)
at Main$Run1.run(Main.java:97)
at java.lang.Thread.run(Thread.java:484)
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Base {}
public class Derived extends Base {}
public class Support
{
private Base base = new Base();
}
import java.net.URL;
import java.net.URLClassLoader;
/**
*
* @version $Revision$
*/
public class Main
{
public static void main(String[] args) throws Exception
{
new Main();
}
private Object lock = new Object();
public Main() throws Exception
{
URL location = getClass().getProtectionDomain().getCodeSource
().getLocation();
URLLoader loader = new URLLoader(new URL[] {location}, getClass
().getClassLoader().getParent());
Class cls = loader.loadClass("Support");
Thread t1 = new Thread(new Run1(cls));
t1.start();
Thread.sleep(1000);
// Load Derived, will trigger a loadClassInternal for Base
loader.loadClass("Derived");
}
public class URLLoader extends URLClassLoader
{
private boolean m_firstTime = true;
public URLLoader(URL[] urls, ClassLoader parent)
{
super(urls, parent);
}
public Class loadClass(String name) throws ClassNotFoundException
{
if (name.equals("Base"))
{
if (m_firstTime)
{
m_firstTime = false;
// Notify the other thread
synchronized (lock)
{
lock.notifyAll();
}
// Wait on the classloader to have the JVM throw
ClassCircularityError
try
{
synchronized (this)
{
wait(5000);
}
}
catch (InterruptedException ignored)
{
}
}
}
return super.loadClass(name);
}
}
public class Run1 implements Runnable
{
private Class cls;
public Run1(Class cls)
{
this.cls = cls;
}
public void run()
{
synchronized (lock)
{
try
{
lock.wait();
}
catch (InterruptedException ignored) {}
}
// Trigger loadClassInternal for Base
try
{
cls.newInstance();
}
catch (Throwable x)
{
x.printStackTrace();
}
}
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
None, unfortunately.
(Review ID: 148304)
======================================================================
- backported by
-
JDK-2139628 ClassCircularityError thrown without reason during class loading
- Closed
- relates to
-
JDK-6341374 api/java_lang/instrument/Instrumentation/index.html#Instrumentation with "-server" causes VM crash
- Closed
-
JDK-8295278 Add parallel class loading tests
- Resolved
-
JDK-4670071 java.lang.ClassLoader.loadClassInternal(String) is too restrictive
- Closed
-
JDK-4940739 placeholder isn't removed by the site that adds it during classloading
- Closed