<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
        <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
        <TITLE> ClassLoaderForTest &lt; HotspotRuntime &lt; JavaSE</TITLE>
        <META NAME="GENERATOR" CONTENT="NeoOffice 2.2  (Unix)">
        <META NAME="CREATED" CONTENT="0;0">
        <META NAME="CHANGED" CONTENT="20081113;10571700">
</HEAD>
<BODY LANG="en-US" DIR="LTR" ONLOAD="initPage()">
<P STYLE="margin-bottom: 0in"><BR>
</P>
<H2><A NAME="Class_Loader_API_Modifications_f"></A>Class Loader API
Modifications for Deadlock Fix 
</H2>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Version .01: November 13, 2008</P>
        <LI><P STYLE="margin-bottom: 0in">Authors: Valerie Peng, Jeff
        Nisewanger, Karen Kinnear 
        </P>
        <LI><P>Audience: Community Review</P>
</UL>
<H3><A NAME="Goals"></A>Goals 
</H3>
<UL>
        <LI><P>The goal of Class Loader API modifications is to resolve a
        critical customer issue: it is easy to deadlock custom class loaders
        that do not adhere to a strict hierarchical class loader delegation
        model. 
        </P>
</UL>
<H3><A NAME="Non_Goals"></A>Non-Goals 
</H3>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Other Class Loader RFEs that
        require API modification will be addressed via individual RFEs,
        separately from this fix for the deadlock problem. 
        </P>
        <LI><P>This proposal does not address any re-architecture for
        performance 
        </P>
</UL>
<H3><A NAME="Motivation"></A>Motivation 
</H3>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Top webbug: 817 SDN votes April
        2008 4670071 java.lang.ClassLoader.loadClassInternal(String) is too
        restrictive 
        </P>
        <LI><P STYLE="margin-bottom: 0in">Causing problems for key customers
        with no good workaround that works for everyone.</P>
</UL>
<H3><A NAME="Technical_Design_Constraints"></A>Technical Design
Constraints 
</H3>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Must allow non-hierarchical class
        delegation topologies without deadlocks 
        </P>
        <LI><P STYLE="margin-bottom: 0in">Must be backwards compatible 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Existing class loaders must
                continue to work unchanged 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Existing code that invokes a
                class loader directly via loadClass(String) or a class loader that
                calls loadClass(String, boolean) must continue to work unchanged 
                </P>
        </UL>
        <LI><P STYLE="margin-bottom: 0in">Must continue to support the
        temporary risky flag combination -XX:+UnlockDiagnosticVMOptions
        -XX:+UnsyncloadClass 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">The intention is to deprecate the
                -XX:+UnsyncloadClass flag when customers adopt the new mechanism. 
                </P>
        </UL>
        <LI><P STYLE="margin-bottom: 0in">Common workaround 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Right now some customers work
                around the deadlock by explicitly issuing a wait() on the class
                loader lock. While this has not been sufficient to solve many
                customers problems, we need to continue to support this until those
                customers have an opportunity to migrate to the new mechanism.</P>
        </UL>
        <LI><P STYLE="margin-bottom: 0in">Must be possible to define
        guidance to migrate custom class loaders to take advantage of
        asynchronous behavior 
        </P>
        <LI><P STYLE="margin-bottom: 0in">Today, with the class loader lock
        held around class loader operations, class loaders are not required
        to handle asynchronous multi-threaded class loading. A mechanism
        which avoids deadlock will require multi-thread safety awareness.
        Given that supporting multi-threaded class loading requires careful
        thought and planning, the new mechanism must provide a way for a
        class loader to explicitly claim that they are multi-thread safe. 
        </P>
        <LI><P STYLE="margin-bottom: 0in">Therefore: the fix for these bugs
        will require code changes by custom class loader authors if their
        class loaders are candidates for deadlock. 
        </P>
        <LI><P STYLE="margin-bottom: 0in">Given that each class loader that
        chooses to adopt the new mechanism must be explicitly safe for
        concurrent class loading by multiple threads, the claim that a class
        loader is multi-thread safe must not be automatically inherited. 
        </P>
        <LI><P STYLE="margin-bottom: 0in">Class loaders that adopt the new
        mechanism must be able to run on older JREs. So, for example, the
        design must allow for a way to detect if the mechanism exists, and
        can not count on inheritance of classes or interfaces that may not
        be present. 
        </P>
        <LI><P STYLE="margin-bottom: 0in">Goal: minimal code changes for
        custom class loader authors 
        </P>
        <LI><P>Goal: If we need to make tradeoffs on how much thought and
        changes are needed for custom class loader authors, depending on
        whether they override findClass(String) or
        loadClass(String)/loadClass(String, boolean), make it simpler for
        those who override findClass(String). There are more of those custom
        class loaders and generally to override either loadClass(...)
        already requires dealing with more class loader complexity. 
        </P>
</UL>
<H3><A NAME="Class_loader_Deadlock_Problem"></A>Class loader Deadlock
Problem 
</H3>
<H4><A NAME="Brief_Overview_of_Class_Loading"></A><A NAME="Brief_Overview_of_Class_Loading_"></A>
Brief Overview of Class Loading Interactions Between Class loader and
the VM 
</H4>
<P>Class loading requires cooperation between the VM and user level
class loaders. Specifically, when the VM is performing constant pool
resolution, among other things, the VM needs to call out to the user
level class loader in order to find and define the requested class.
On the other side, the class loader responsible for loading a class
needs to call into the VM to determine if the class has already been
loaded (findLoadedClass), and to define the class based on a bytecode
stream (defineClass). 
</P>
<P>The current recommended logic in detail is: 
</P>
<PRE>                 User Level Class Loader                               VM
                                                            constant pool resolution
                                                            first acquire class loader lock
  --&gt;private synchronized loadClassInternal(String)    &lt;--- calls out to loadClassInternal(String)
  |     public loadClass(String)                             
  |       protected synchronized loadClass(String,boolean) 
  |         protected final findLoadedClass(...)             ---&gt;  VM SystemDictionary cache lookup
  |                                                                (can not trigger further class loading)
  |         delegate (e.g. parent.loadClass(String))
  |         protected findClass(String)  
  |           reads in bytes
  |           protected final defineClass(...)               ---&gt; resolves superclasses and superinterfaces
  |                                                               which recursively calls out to
  --------------------------------------------------   &lt;---       loadClassInternal(String)   </PRE><P>
Custom class loader authors are encouraged to override
findClass(String) to allow them to determine where or how the byte
code stream is obtained. Some custom class loader authors override
loadClass (String) or loadClass(String, boolean) to be able to change
the delegation strategy. 
</P>
<P>Currently many class loading interactions are synchronized on the
class loader lock. This works well for class loader delegation that
assumes a strictly tree based delegation hierarchy. 
</P>
<P>Customers have requested the ability to delegate to arbitrary
class loaders. Currently this can cause deadlocks if class loaders
delegate to each other without a fixed ordering.</P>
<H4><A NAME="Sample_Deadlock_Scenario_non_tre"></A>Sample Deadlock
Scenario: non-tree based delegation hierarchy 
</H4>
<PRE>Class Hierarchy:
  class A extends B
  class C extends D

ClassLoader Delegation Hierarchy:

Custom Classloader CL1:
  directly loads class A 
  delegates to custom ClassLoader CL2 for class B

Custom Classloader CL2:
  directly loads class C
  delegates to custom ClassLoader CL1 for class D

Thread 1:
  Use CL1 to load class A (locks CL1)
    defineClass A triggers
      loadClass B (try to lock CL2)

Thread 2:
  Use CL2 to load class C (locks CL2)
    defineClass C triggers
      loadClass D (try to lock CL1)</PRE><H3>
<A NAME="Proposed_Solution"></A>Proposed Solution 
</H3>
<PRE>                 User Level Class Loader                                   VM
                                                              constant pool resolution 
                                                              If ParallelCapable:lock class/class loader pair
                                                                 else acquire class loader lock
       *DEPRECATE*: private synchronized loadClassInternal    
  |--&gt;public loadClass(String)                          &lt;---  calls out to loadClass(String)
  |      call loadClass(String,boolean) (*no longer synchronized*)
  |         *if ParallelCapable:* 
  |           *synchronize on a class-name-based-lock*
  |           *else synchronize on &quot;this&quot; (backward compatibility)*
  |         protected final findLoadedClass(...)              ---&gt;  VM SystemDictionary cache lookup
  |                                                                 (can not trigger further class loading)
  |         delegate (e.g. parent.loadClass(String))
  |         protected findClass(String)  
  |           reads in by
  |           protected final defineClass(...)                ---&gt; resolves superclasses and superinterfaces
  |                                                                which recursively calls out to
  --------------------------------------------------     &lt;---      loadClass(String) </PRE><H4>
<A NAME="API_Modifications"></A>API Modifications 
</H4>
<H5><A NAME="Java_APIs"></A>Java APIs 
</H5>
<UL>
        <LI><P STYLE="margin-bottom: 0in">New protected static method in
        java.lang.ClassLoader, boolean registerAsParallelCapable() 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">To be called once from class
                initialization of a subclass of java.lang.ClassLoader which
                supports parallel loading of classes. 
                </P>
                <LI><P STYLE="margin-bottom: 0in">In order for a a class loader
                class to register itself as parallel capable, all of its
                superclasses which are instances of java.lang.ClassLoader must also
                already be registered as parallel capable when invoking this
                protected static method. Otherwise the request will be ignored. 
                </P>
                <LI><P STYLE="margin-bottom: 0in">registerAsParallelCapable() will
                return true if the class loader successfully registers as
                parallelCapable, even if accidentally called a second time. It will
                return false on failure. 
                </P>
        </UL>
        <LI><P STYLE="margin-bottom: 0in">java.lang.ClassLoader API changes:
                </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Deprecate private
                loadClassInternal(), retain temporarily for backward compatibility 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Remove the synchronized keyword
                from: 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">protected synchronized Class&lt;?&gt;
                        loadClass(String name, boolean resolve) method. 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">public synchronized void
                        setDefaultAssertionStatus(boolean enabled) 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">public synchronized void
                        setPackageAssertionStatus(String packageName, boolean enabled) 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">public synchronized void
                        setClassAssertionStatus(String className, boolean enabled) 
                        </P>
                        <LI><P>public synchronized void clearAssertionStatus() 
                        </P>
                </UL>
        </UL>
</UL>
<H5><A NAME="VM_Flags_for_early_access_testin"></A>VM Flags for early
access testing 
</H5>
<UL>
        <LI><P STYLE="margin-bottom: 0in">AlwaysLockClassLoader - default
        false. Provided for ParallelClassLoader that has a bug in handling
        multiple threads in parallel. Expected to ship in product. 
        </P>
        <LI><P STYLE="margin-bottom: 0in">AllowParallelDefineClass - default
        false. If two threads try to define the same class/class loader pair
        in parallel, throw linkageError, duplicate class definition. If you
        change the flag, we would allow parallel defineClass requests, using
        the result of the first requester. This would require a JVMS
        clarification. Experimental in product for early access feedback
        only, not expected to ship. 
        </P>
        <LI><P>MustCallLoadClassInternal - default false. In case a customer
        actually depended on this call, perhaps expecting to find this on
        the stack. Note that this will only enforce calling
        loadClassInternal(String). For instances of parallel capable class
        loaders, neither the VM nor loadClassInternal(String) will acquire
        the class loader lock. Expected to ship in product for one or two
        releases until deprecated loadClassInternal(String) can be safely
        removed. 
        </P>
</UL>
<H5><A NAME="Java_VM_interface_changes"></A>Java &lt;-&gt; VM
interface changes 
</H5>
<UL>
        <LI><P STYLE="margin-bottom: 0in">VM calls loadClass(String) NOT
        loadClassInternal(String) always (note: backward compatibility
        -XX:+MustCallLoadClassInternal flag override) 
        </P>
        <LI><P STYLE="margin-bottom: 0in">VM acquires class loader lock only
        if class loader instance is not a ParallelCapable class 
        </P>
        <LI><P>java.lang.ClassLoader's instance constructor will look up the
        class for a new class loader, and if it is registered as parallel
        capable, set a private instance field, parallelLockMap to non-null
        for the vm to query. 
        </P>
</UL>
<H4><A NAME="Class_Loader_changes_required"></A><A NAME="Class_Loader_changes_required_"></A>
Class Loader changes required</H4>
<UL>
        <LI><P STYLE="margin-bottom: 0in">java.lang.ClassLoader: 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Invoke
                registerAsParallelCapable() during class initialization 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Modify the code to ensure
                thread-safe concurrency 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">Ensure no internal methods
                        synchronize on the class loader object for parallel capable class
                        loaders 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">Ensure all critical sections are
                        safe when executed by multiple threads loading different classes 
                        </P>
                </UL>
                <LI><P STYLE="margin-bottom: 0in">protected loadClass(String,
                boolean) changes: 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">Remove synchronized keyword 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">If &quot;this&quot; is not a
                        parallel capable class loader, synchronize on &quot;this&quot; for
                        backward compatibility 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">else synchronize on a
                        class-name-based-lock 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">The synchronization in protected
                        loadClass(String, boolean) ensures that defineClass(...) will not
                        be called multiple times in parallel for the same class name/class
                        loader pair. 
                        </P>
                </UL>
                <LI><P STYLE="margin-bottom: 0in">AssertionStatus related APIs 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">Replace synchronized keyword
                        with internal synchronization logic for: 
                        </P>
                        <UL>
                                <LI><P STYLE="margin-bottom: 0in">public synchronized void
                                setDefaultAssertionStatus(boolean enabled) 
                                </P>
                                <LI><P STYLE="margin-bottom: 0in">public synchronized void
                                setPackageAssertionStatus(String packageName, boolean enabled) 
                                </P>
                                <LI><P STYLE="margin-bottom: 0in">public synchronized void
                                setClassAssertionStatus(String className, boolean enabled) 
                                </P>
                                <LI><P STYLE="margin-bottom: 0in">public synchronized void
                                clearAssertionStatus() 
                                </P>
                        </UL>
                        <LI><P STYLE="margin-bottom: 0in">Internal synchronization logic: 
                        </P>
                        <UL>
                                <LI><P STYLE="margin-bottom: 0in">If &quot;this&quot; is not a
                                ParallelCapable class loader, synchronize on &quot;this&quot; for
                                backward compatibility 
                                </P>
                                <LI><P STYLE="margin-bottom: 0in">else synchronize on a dedicated
                                internal lock object for all assertion related fields 
                                </P>
                        </UL>
                </UL>
                <LI><P STYLE="margin-bottom: 0in">add new protected static method:
                registerAsParallelCapable() 
                </P>
                <UL>
                        <LI><P>If all superclasses which are instances of
                        java.lang.ClassLoader succeeded in registering as ParallelCapable,
                        the calling class will also successfully register as parallel
                        capable. 
                        </P>
                </UL>
        </UL>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">java.security.SecureClassLoader 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Invoke
                registerAsParallelCapable() during class initialization 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Modify the code to ensure
                thread-safe concurrency 
                </P>
                <UL>
                        <LI><P>Actually, no modifications were necessary 
                        </P>
                </UL>
        </UL>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">java.net.URLClassLoader: 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Invoke
                registerAsParallelCapable() during class initialization 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Modify the code to ensure
                thread-safe concurrency 
                </P>
                <UL>
                        <LI><P>details: TBD 
                        </P>
                </UL>
        </UL>
</UL>
<H4><A NAME="Suggested_Model_for_Custom_Class"></A>Suggested Model
for Custom Class Loaders 
</H4>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Custom class loaders that have no
        history of deadlocks require no changes. 
        </P>
        <LI><P STYLE="margin-bottom: 0in">Custom class loaders that support
        a non-hierarchical delegation model and so are candidates for
        deadlock may choose to adopt the new mechanism. If you adopt this
        new mechanism, you need to modify all custom class loaders that
        could interact in a deadlock. 
        </P>
        <LI><P>Current class loaders frequently rely on the synchronization
        on the class loader lock provided by the enclosing methods
        loadClassInternal and protected loadClass(String, boolean). To
        resolve the current deadlocking on class loader locks, finer grained
        locking is needed. For class loader classes that successfully
        register themselves as parallel capable, the java.lang.ClassLoader
        class will no longer synchronize on the current class loader object
        when called to load a class. Instead java.lang.ClassLoader uses its
        own private lock which is unique for each class name. This allows
        concurrent loading of different classes for the same class loader
        instance. This locking logic is in the protected loadClass(String,
        boolean) method and will be passed to custom parallel class loaders
        through inheritance if not overridden. 
        </P>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Recommended modifications for
        custom class loaders that need to avoid deadlocks: 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">1. REQUIRED: In the class
                initializer, invoke java.lang.ClassLoader
                registerAsParallelCapable() 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">This registration indicates that
                        all instances of this class loader class are multi-thread safe for
                        concurrent class loading 
                        </P>
                        <LI><P>If the registration succeeds, java.lang.ClassLoader will
                        allow concurrent loading of classes for the same class loader
                        instance 
                        </P>
                </UL>
        </UL>
</UL>
<UL>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">2. REQUIRED: Modify the code to
                ensure multi-thread safety 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">Decide upon an internal locking
                        scheme. E.g. java.lang.ClassLoader uses a class-name-based locking
                        scheme. 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">Remove all synchronization on
                        the class loader lock 
                        </P>
                        <LI><P>Ensure that critical sections are safe for multiple threads
                        loading different classes. 
                        </P>
                </UL>
        </UL>
</UL>
<UL>
        <UL>
                <LI><P>3. REQUIRED: Ensure that all class loader classes that this
                custom class loader extends also invoke registerAsParallelCapable()
                in the class initializer and ensure they are multi-thread safe for
                concurrent class loading 
                </P>
        </UL>
</UL>
<UL>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">4.a Class loaders that invoke
                registerAsParallelCapable(), that override findClass(String),
                (recommended overriding): 
                </P>
                <UL>
                        <LI><P>No further modifications required 
                        </P>
                </UL>
        </UL>
</UL>
<UL>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">4.b. Class loaders that invoke
                registerAsParallelCapable(), that override protected
                loadClass(String, boolean) or public loadClass(String) 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">We recommend that you override
                        findClass(String) instead, if at all possible 
                        </P>
                        <LI><P>To ensure that the protected defineClass(...) method is
                        only called once for the same class name, you need to implement a
                        finer-grained locking scheme. One option would be to adopt the
                        class name based locking mechanism from java.lang.ClassLoader's
                        protected loadClass(String, boolean) method. 
                        </P>
                </UL>
        </UL>
</UL>
<H3><A NAME="Internal_Implementation_Details"></A>Internal
Implementation Details 
</H3>
<P>The most important point to make is that all class loaders that
want the deadlock fix, must be cleaned up to ensure that they are
multi-thread safe, i.e. that they allow the class loader to load
multiple classes at the same time. The basic approach is to remove
synchronization on the class loader itself, and provide smaller
granularity locking for critical sections. It is critical that there
be no synchronization on the class loader lock for parallel capable
class loaders. Given that class loading is frequently triggered
implicitly, e.g. by newInstance, and given the interactions between
the VM and class loaders, acquiring the class loader lock holds the
risk of causing a deadlock. 
</P>
<P>All of the JRE class loaders which customers extend to create
custom class loaders need to invoke registerAsParallelCapable(). They
all must be made multi-thread safe for concurrent class loading of
different class name/class loader pairs, so methods inherited by
parallel capable custom class loaders are thread-safe. These include:
</P>
<UL>
        <LI><P STYLE="margin-bottom: 0in">java.lang.ClassLoader 
        </P>
        <LI><P STYLE="margin-bottom: 0in">java.security.SecureClassLoader 
        </P>
        <LI><P STYLE="margin-bottom: 0in">java.net.URLClassLoader 
        </P>
        <LI><P STYLE="margin-bottom: 0in">javax.management.loading.MLet 
        </P>
        <LI><P>javax.management.loading.PrivateMlet 
        </P>
</UL>
<P>All of the JRE class loaders which custom class loaders delegate
to in the traditional tree-based hierarchy in theory would not
require changes due to delegation. Given that they are supposed to
only delegate further up the hierarchy, they should not participate
in a deadlock. If at a future time any of these class loaders were to
adopt an alternative delegation policy, that for instance would allow
more direct delegation to a specific class loader, then it would be
necessary to make these class loaders multi-thread safe. 
</P>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Bootstrap class loader 
        </P>
        <LI><P STYLE="margin-bottom: 0in">Extension class loader:
        sun.misc.Launcher$ExtClassLoader 
        </P>
        <LI><P STYLE="margin-bottom: 0in">System class loader 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">sun.misc.launcher.AppClassLoader 
                </P>
                <LI><P>sun.Applet.AppletClassLoader 
                </P>
        </UL>
</UL>
<P>Other class loaders, that are not extended and not delegated to by
custom class loaders do not require any changes. These include: 
</P>
<UL>
        <LI><P STYLE="margin-bottom: 0in">java.rmi.server.RMIClassLoader 
        </P>
        <LI><P STYLE="margin-bottom: 0in">com.sun.jnlp.JNLPClassLoader 
        </P>
        <LI><P STYLE="margin-bottom: 0in">All sun.* packages are private and
        customers can not extend 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">sun.plugin.javascript.JSClassLoader
                                </P>
                <LI><P STYLE="margin-bottom: 0in">sun.plugin.security.PluginClassLoader
                                </P>
                <LI><P STYLE="margin-bottom: 0in">sun.plugin2.applet.JNLP2ClassLoader
                                </P>
                <LI><P STYLE="margin-bottom: 0in">sun.plugin2.applet.Applet2ClassLoader
                                </P>
                <LI><P>sun.plugin2.applet.Plugin2ClassLoader 
                </P>
        </UL>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Assumptions: 
        </P>
        <UL>
                <LI><P>The DownloadManager does not load classes, it copies down
                files and the bootstrap class loader retries. 
                </P>
        </UL>
</UL>
<H4><A NAME="VM_Behavior_Changes1"></A>VM Behavior Changes 
</H4>
<P>Part of the Sincere apologies on how long it has taken us to fix
this problem. Part of the reason this fix has taken so long is that
we first needed to modify the VM in the following ways:</P>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Fixed problems with circularity
        detection (JDK5)</P>
        <LI><P STYLE="margin-bottom: 0in">Modified the bootstrap class
        loader to be a parallel class loader (JDK6)</P>
        <LI><P STYLE="margin-bottom: 0in">Modified the VM common class
        resolution logic to handle parallel class loading (HotSpot 10)</P>
</UL>
<H5>Details of VM handling of different cl Details of VM handling of
specific class loader cases:</H5>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Traditional class loaders 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">JDK 6: lock class loader object
                lock, call loadClassInternal(String)</P>
                <LI><P STYLE="margin-bottom: 0in">New: when using traditional class
                loaders to load classes, lock class loader object lock, call
                loadClass(String) 
                </P>
        </UL>
        <LI><P STYLE="margin-bottom: 0in">-XX:+UnlockDiagnosticOptions
        -XX:+UnsyncloadClass - DEPRECATED 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">JDK 6: no class loader object
                lock for class loaders, call loadClass(String) 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">allow parallel overall class
                        resolution, parallel superclass loading, and parallel
                        defineClass() calls 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">parallel defineClass() handling:
                        if there are two define class requests at the same time for the
                        same class/class loader pair, the second requestor waits for the
                        first requestor and returns the first requestor's results, instead
                        of throwing a linkageError. 
                        </P>
                </UL>
                <LI><P STYLE="margin-bottom: 0in">New: support for flags is the
                same as in JDK6</P>
        </UL>
        <LI><P STYLE="margin-bottom: 0in">parallelCapable 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">JDK 6: same behavior as
                traditional class loaders</P>
                <LI><P STYLE="margin-bottom: 0in">New: no class loader object lock
                for class loaders, call loadClass(String) 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">allow parallel overall class
                        resolution, and parallel superclass loading 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">parallel defineClass requests
                        will throw LinkageErrors (for early access experimentation: see
                        AllowParallelDefineClass flag) 
                        </P>
                </UL>
        </UL>
        <LI><P STYLE="margin-bottom: 0in">bootstrap class loader 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">JDK6: no global lock, allow
                parallel overall class resolution</P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">wait for parallel superclass
                        loads to complete 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">parallel defineClass requests
                        will throw LinkageErrors</P>
                </UL>
                <LI><P STYLE="margin-bottom: 0in">New: same as JDK6</P>
        </UL>
        <LI><P STYLE="margin-bottom: 0in">breaking the class loader lock 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">JDK6: special handling: for both
                overall class resolution and superclass loads: first requestor
                completes, others wait for completion 
                </P>
                <LI><P>New: same as JDK6</P>
        </UL>
</UL>
<H3><A NAME="Alternatives_Considered_and_Not"></A><A NAME="Alternatives_Considered_and_Not_"></A>
Alternatives Considered and Not Chosen 
</H3>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Marker interface. 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Proposal: Provide a marker
                interface which a class loader can implement to declare that it is
                a parallel capable class loader. 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Reasons not chosen: 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">It is key that a custom class
                        loader not inherit registration as a parallel capable class
                        loader. 
                        </P>
                        <LI><P>For class loaders to be able to run both with this new
                        mechanism and on older JREs, we need a mechanism that has a way to
                        dynamically check if the new mechanism is in place. With a new
                        API, the class loader can check for the existence of the new
                        method to determine whether the JRE supports parallel
                        classloading. We can't extend an interface or subclass a new class
                        which did not exist on an older version. 
                        </P>
                </UL>
        </UL>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Annotations 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Proposal: Use annotations to
                indicate that a class loader is parallelCapable. 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Reason not chosen: 
                </P>
                <UL>
                        <LI><P>Annotations were explicitly designed to NOT modify VM
                        runtime behavior, only to provide information, i.e. annotations
                        were not intended to be a macro language for the VM. If run on a
                        VM that does not understand an annotation, the behavior should not
                        change. 
                        </P>
                </UL>
        </UL>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">new loadClassXXX(String) API
        instead of registration 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Proposal: Add a new protected
                method loadClass2(String). The VM calls loadClass2(String), which
                acquires the class loader lock and then calls loadClass(String).
                Class loaders that support parallel loading override
                loadClass2(String) so that it takes a per-class-name lock instead
                and then calls loadClass(String). This also requires removing the
                synchronized keyword from loadClass(String, boolean). 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Reasons not chosen: 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">The VM would have not way of
                        knowing if the class loader supports parallel class loading or
                        not. For prevent deadlock the VM needs to allow parallel class
                        resolution and parallel superclass loading. For backward
                        compatibility, the VM needs to not allow parallel class resolution
                        and parallel superclass loading. 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">There are multiple paths into
                        class loading today which must continue to work for backward
                        compatibility. 
                        </P>
                        <UL>
                                <LI><P>Custom class loaders that call loadClass(String, boolean)
                                must continue to work, so for them, loadClass(String, boolean)
                                needs to acquire the class loader lock if they are calling an
                                existing class loader, or not acquire the lock if they are
                                calling a parallel capable class loader. 
                                </P>
                        </UL>
                </UL>
        </UL>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">new loadClassXXX(String) API in
        addition to registration mechanism 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Proposal: In addition to a
                registration mechanism, introduce a new protected
                loadClassUnsync(String, boolean) that is not synchronized. Change
                protected synchronized loadClass(String, boolean) to simply call
                loadClassUnsync(String, boolean). VM calls loadClass(String) which
                dispatches to loadClass(String, boolean) or loadClassUnsync(String,
                boolean) depending on whether the class loader is parallel capable
                or not. 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Reasons not chosen: 
                </P>
                <UL>
                        <LI><P STYLE="margin-bottom: 0in">Strongly considered and in fact
                        prototyped. While we believe this could work technically, we
                        believe the current proposal is the simplest we have so far
                        devised in terms of requiring minimal changes for custom class
                        loader authors who need to deal with deadlocks, and no changes for
                        others. 
                        </P>
                        <LI><P STYLE="margin-bottom: 0in">Requires both the same changes
                        the current proposal does for custom class loader author and
                        additional changes: 
                        </P>
                        <UL>
                                <LI><P STYLE="margin-bottom: 0in">All custom class loader authors
                                would need to provide their own synchronization mechanism, i.e.
                                we would not provide the per-class-name synchronization that we
                                do today 
                                </P>
                                <LI><P>Custom class loader authors that currently override
                                findClass(String) would now need to provide
                                loadClassUnsync(String, boolean), i.e. essentially needing to
                                override loadClass(String, boolean) functionality. Our goal is to
                                encourage custom class loader authors, particularly those that
                                just want to modify where classes are found, to only have to
                                override findClass(String). 
                                </P>
                        </UL>
                </UL>
        </UL>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Per-instance
        registerAsParallelCapable(): 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Proposal: Instead of registering
                a class loader class as parallel capable, register a single class
                loader instance. 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Reason not chosen. Not needed. 
                </P>
                <UL>
                        <LI><P>The registration is intended to inform that a class loader
                        is multi-thread safe. That information is meaningful on a
                        per-class bases. If a custom class loader author wishes, they can
                        go back to locking on the classloader object for instances in
                        which they would like to disable the parallel class loading
                        capability in their implementation. By registering as
                        parallelCapable, they have that option. Tracking of parallel
                        capable is based on the Class instance of the class loader which
                        registered as parallel capable and not based on the class name. So
                        if multiple custom loaders choose the same class name, or if
                        someone chooses to load the same class loader classfile with
                        different class loaders, those will be tracked independently.</P>
                </UL>
        </UL>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">New LinkageError for parallel
        duplicate requests 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Proposal: It has been suggested
                that one way of handing parallel duplicate requests would be to
                define a new LinkageError subclass passing back the original
                defined class, rather than the current error of &quot;duplicate&quot;.
                I think the intention of this proposal was that the caller of
                defineClass() could check if the original class matched the
                requested class, and if so, do a findLoadedClass() to use the
                previously defined class. 
                </P>
                <LI><P>Reason not chosen: A problem with the proposal is that the
                VM does not actually cache the original unprocessed bytestream, and
                it would not be worth the overhead to do so. 
                </P>
        </UL>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Ability to override the
        requirement that all superclasses must be parallelCapable. 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Proposal: Some custom class
                loader authors would like to state that a given class loader is
                parallelCapable and they guarantee that all superclasses are
                parallelCapable even though they are not registered as such. 
                </P>
                <LI><P STYLE="margin-bottom: 0in">Reasons not chosen: 
                </P>
                <UL>
                        <LI><P>A strong concern is that authors of the superclass would
                        not know that future changes would be expected to support the
                        multi-thread safety that parallelCapable implies, and so there
                        would be a strong risk of breaking undocumented, unofficial,
                        backward compatibility. 
                        </P>
                </UL>
        </UL>
</UL>
<H3><A NAME="Open_Issues"></A>Open Issues 
</H3>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Use the term Async instead of
        parallelCapable 
        </P>
        <UL>
                <LI><P>Naming suggestions are welcome 
                </P>
        </UL>
</UL>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Modify JVMS and defineClass(...)
        behavior 
        </P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Proposal: There is a suggestion
                to modify defineClass() behavior such that for parallel capable
                class loaders, if two defineClass(...) requests for the same
                class/class loader pair occur in parallel, rather than throwing a
                LinkageError for a duplicate definition, defineClass() would have
                enforce first-definition-wins-behavior. All defineClass(...)
                requests would parse the byte stream for ClassFileFormatError. The
                first requester will complete the definition process, subsequent
                requestors will wait and use the results of the first request. 
                </P>
                <LI><P STYLE="margin-bottom: 0in">The prototype will offer a flag,
                -XX:+AllowParallelDefineClass so that you can provide feedback
                based on experimentation.</P>
        </UL>
</UL>
<P STYLE="margin-bottom: 0in"><BR>
</P>
<UL>
        <LI><P STYLE="margin-bottom: 0in">Protected method for subclass
        re-use for the default locking model</P>
        <UL>
                <LI><P STYLE="margin-bottom: 0in">Proposal: Provide a method in
                java.lang.ClassLoader that would allow subclasses to re-use the
                default per-class-name locking model, making modifications easier
                for custom loaders that override loadClass(...). Current prototype:
                Object getClassLoadingLock(String className) which will either
                return the per-class-name lock for that class loader, or the class
                loader object for non-parallel capable class loaders. This allows
                the caller to just synchronize on the result without having to know
                whether the current class loader is parallel capable or not.</P>
                <LI><P STYLE="margin-bottom: 0in">Another less common scenario for
                use would be if a custom non-parallel capable class loader extends
                a parallel capable class loader. If the parallel capable class
                loader invokes loadCass(...) on the non-parallel subclass, and the
                subclass does not override loadClass(...), the common
                loadClass(...) logic may wish to synchronize on the appropriate
                lock depending on whether the current class loader is parallel
                capable or not.</P>
                <LI><P STYLE="margin-bottom: 0in">Please let us know if you need
                this API. Given the goal of simplicity, we will only add APIS that
                are deemed must-haves. Also, by default we would mark this API
                final. If you need this to be able to override this API let us
                know.</P>
        </UL>
</UL>
<P STYLE="margin-bottom: 0in"><BR>
</P>
<H3><BR><BR>
</H3>
</BODY>
</HTML>