JDK-4406709 : change in class loading in jdk 1.3 causes customer app to deadlock
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.3_01
  • Priority: P2
  • Status: Closed
  • Resolution: Not an Issue
  • OS: solaris_2.6
  • CPU: sparc
  • Submitted: 2001-01-22
  • Updated: 2001-03-02
  • Resolved: 2001-03-02
Related Reports
Relates :  
Description
Wanted to get this logged but still working with customer and engineering to
determine if this is a bug in the customers app or a jdk 1.3 issue.



I wonder if you could help us with a rather serious problem we're seeing
>	with the Standard Edition JDK 1.3 release?  It appears that the contract
>	between the Java VM and the ClassLoader has changed in a subtle but
>	important way in JDK 1.3 compared to previous releases: in JDK 1.3 when
>	the VM needs to load a class (e.g. to resolve a dynamically-linked 
>reference),
>	the VM calls a new private method on java.lang.ClassLoader called
>	"loadClassInternal".  This private method is synchronized on the class
>	loader object, and that's what causes the problem.
>	
>	In prior releases, the VM simply called the loadClass(String) method on
>	the class loader, which was NOT synchronized; this gave the class loader
>	the opportunity to manage its own synchronization by appropriately
>	overloading the loadClass(String) or loadClass(String, boolean) methods.
>	Now, however, the class loader has no control over synchronization -- 
>because
>	loadClassInternal is private and synchronized, the class loader is
>	always called with the lock on the class loader object held.
>	
>	SilverStream uses a rather complicated class loading scheme to try to
>	permit on-the-fly replacement of classes in a running app server; this
>	involves using multiple class loaders including one which implements
>	class path semantics (e.g. first look in Jar file A, then in Jar file
>	B, etc.)  This means that we often need to call more than one class
>	loader in the course of loading a class, and that sometimes a call
>	to loadClass() on class loader A actually results in the class being
>	loaded (and defined) by class loader B.  This no longer works reliably
>	in JDK 1.3, because of deadlocks introduced by the new synchronized
>	loadClassInternal method -- if the VM calls class loader A's
>	loadClassInternal method, class loader A is now locked; A then must
>	call a synchronized method in B.  Other threads can perform these
>	operations in the opposite order, resulting in a deadlock.
>	
>	We think that the change to use the synchronized loadClassInternal()
>	method was an incompatible semantic change to class loading.  We'd
>	like to request that either:
>	 1) The change be backed out; or
>	 2) The loadClassInternal() method be made protected, so we can
>	    overload it in our class loaders to avoid the deadlock.
>	
>	Can you please contact the appropriate engineers in the JDK group
>	to find out why this change was made and what the prospects for a
>	fix to our problem are?  Needless to say, this is pretty high-priority
>	for us -- customers have already reported this deadlock when using
>	the SilverStream application server with JDK 1.3, and we have no
>	workaround for them at present.
>	

Comments
EVALUATION As has been mentioned in emails to the customer, the VM locks the classloader internally before it makes the upcall to loadClassInternal. For this reason the "synchronized" statement is actually a no-op. This hang would almost certainly have been reproducible under 1.2 as well. kenneth.russell@eng 2001-02-09 fred.oliver@East 2001-03-01 In the 1.3 case, HotSpot locks the ClassLoader object BEFORE beginning the search for the class, and holds the lock until the loading of the class (and superclasses, interfaces, etc.) is complete. In the 1.2 case (assuming the production release for Solaris), ExactVM locks the ClassLoader object AFTER the search for the class, during the definition of the class, and holds the lock until the loading of the class (and superclasses, interfaces, etc.) is complete. It is the fact that ExactVM locked the ClassLoader at a slightly later time which allows the multi-threaded behavior demonstrated by this customer application. While the class loading strategy this particular application uses appears to work with ExactVM, loading base classes from delegated classloaders in parallel, it should be able to contrive a similar situation using superclasses are loaded from delegated classloaders which deadlocks ExactVM as well. fred.oliver@East 2001-03-02 In my view the HotSpot behavior is more correct with respect to the JVM Specification, section 5.3.2. If a JVM allowed multiple calls to an initiating classloader's loadClass (or loadClassInternal), and if those calls delegated to different defining classloaders, then the JVM would not be able to choose between them. http://java.sun.com/docs/books/vmspec/2nd-edition/html/ConstantPool.doc.html#79441 This is not a bug in the 1.3 SDK (it's a bug in the 1.2 SDK which allowed this behavior). Perhaps it is possible for some of the synchronized methods in the customer's classloaders to be moved to separate objects, so that they are not affected by the classloader's locks. fred.oliver@East 2001-03-02 Also, the requirement that loadClass() be called once is mentioned in the following paper: http://java.sun.com/people/gbracha/classloaders.ps
02-03-2001