You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@harmony.apache.org by Alex Blewitt <al...@gmail.com> on 2006/08/03 22:41:41 UTC

Fwd: Re: [equinox-dev] buddy classloading & deadlock

This message came up on equinox-dev recently. It highlights a
potential deadlock when the Sun VM locks the classloader prior to
calling loadClassInternal. I have no idea if this is an issue for the
VM we're using, but if it is, we ought to consider what can be done to
fix it.

Alex.

---------- Forwarded message ----------
From: Thomas Watson
Date: 03-Aug-2006 16:32
Subject: Re: [equinox-dev] buddy classloading & deadlock
To: Equinox development mailing list



What vendor/version of the VM are you using?

There has been a long standing bug open against Sun on a similar
issue.  It all boils down to the native VM locking the classloader
before loading a class from it using the ClassLoader.loadClassInternal
method.  In your stacktrace below this happens when the VM calls
ClassLoader.loadClassInternal
(DefaultClassLoader(ClassLoader).loadClassInternal(String) line: 319).
 The VM locks the classloader in native code before it ever calls into
the ClassLoader.  This leaves us with no options, even if we override
the loadClassInternal method to make it non-synchronized it will make
no difference because the native code locks the ClassLoader no matter
what the method signature is for loadClassInternal.  I have been told
that Sun plans to fix this in a future release of the VM, it may be
fixed in the latest 1.5 Sun VM.  The IBM VMs have fixed this issue,
they will NOT lock the classloader before invoking it from the native
VM code.

Tom

---

 Hi all,

 I noticed that multithreading combined with buddy classloading can
 produce some scary deadlocks. I had one in a project last week and
 managed to recreate it in a toy example. Now I'm wondering if this is
 just one of the dangers of breaking the classloading hierarchy or if
 the framework could do something to avoid this ?

 My toy example (also in attachment):

 The main project has just one Application class:

 public class Application implements IPlatformRunnable{

                 public Object run(Object args) throws Exception {
                                  new Activator();
                                  return true;
                 }

 }


 and the dependent project has an Activator

 public class Activator implements BundleActivator {

 public void start(BundleContext context) throws Exception {
  new Thread(new Runnable() {
                 public void run() {
                 try {
                    Class.forName("main.Application");
                } catch (ClassNotFoundException e) { }
  }).start();

  // let other thread run to induce deadlock
  try { Thread.sleep(100); } catch (InterruptedException e) {}
 }

 public void stop(BundleContext context) throws Exception {}

 }


 The main project depends on dependent, and the dependent project has a
 global buddy policy.


 This causes the following deadlock:

 Thread [main] (Suspended)
                 owns: DefaultClassLoader  (id=16)
                 waiting for: DefaultClassLoader  (id=15)
                 ClasspathManager.findLocalClassImpl(String,
ClassLoadingStatsHook[]) line: 422
                 ClasspathManager.findLocalClass(String) line: 410
                 DefaultClassLoader.findLocalClass(String) line: 188
                 BundleLoader.findLocalClass(String) line: 339
                 SingleSourcePackage.loadClass(String) line: 37
                 BundleLoader.findClass(String, boolean) line: 388
                 BundleLoader.findClass(String) line: 352
                 DefaultClassLoader.loadClass(String, boolean) line:
83
                 DefaultClassLoader(ClassLoader).loadClass(String)
line: 251

DefaultClassLoader(ClassLoader).loadClassInternal(String) line: 319
                 Application.run(Object) line: 11
                 PlatformActivator$1.run(Object) line: 78
                 EclipseAppLauncher.runApplication(Object) line: 92
                 EclipseAppLauncher.start(Object) line: 68
                 EclipseStarter.run(Object) line: 400
                 EclipseStarter.run(String[], Runnable) line: 177
                 NativeMethodAccessorImpl.invoke0(Method, Object,
Object[]) line: not
 available [native method]
                 NativeMethodAccessorImpl.invoke(Object, Object[])
line: 39
                 DelegatingMethodAccessorImpl.invoke(Object, Object[])
line: 25
                 Method.invoke(Object, Object...) line: 585
                 Main.invokeFramework(String[], URL[]) line: 336
                 Main.basicRun(String[]) line: 280
                 Main.run(String[]) line: 977
                 Main.main(String[]) line: 952

 Thread [Thread-1] (Suspended)
                 owns: DefaultClassLoader  (id=15)
                 waiting for: DefaultClassLoader  (id=16)
                 ClasspathManager.findLocalClassImpl(String,
ClassLoadingStatsHook[]) line: 422
                 ClasspathManager.findLocalClass(String) line: 410
                 DefaultClassLoader.findLocalClass(String) line: 188
                 BundleLoader.findLocalClass(String) line: 339
                 BundleLoader.findClass(String, boolean) line: 391
                 BundleLoader.findClass(String) line: 352
                 DefaultClassLoader.loadClass(String, boolean) line:
83
                 DefaultClassLoader(ClassLoader).loadClass(String)
line: 251
                 BundleLoader.loadClass(String) line: 276
                 BundleHost.loadClass(String, boolean) line: 227
                 BundleHost(AbstractBundle).loadClass(String) line:
1245
                 GlobalPolicy.loadClass(String) line: 39
                 PolicyHandler.doBuddyClassLoading(String) line: 138
                 BundleLoader.findClass(String, boolean) line: 402
                 BundleLoader.findClass(String) line: 352
                 DefaultClassLoader.loadClass(String, boolean) line:
83
                 DefaultClassLoader(ClassLoader).loadClass(String)
line: 251

DefaultClassLoader(ClassLoader).loadClassInternal(String) line: 319
                 Class<T>.forName0(String, boolean, ClassLoader) line:
not available
 [native method]
                 Class<T>.forName(String) line: 164
                 Activator$1.run() line: 12
                 Thread.run() line: 595
 [attachment "buddy-classloading-deadlock.zip" deleted by Thomas
Watson/Austin/IBM] _______________________________________________
 equinox-dev mailing list
 https://dev.eclipse.org/mailman/listinfo/equinox-dev


_______________________________________________
equinox-dev mailing list
https://dev.eclipse.org/mailman/listinfo/equinox-dev

---------------------------------------------------------------------
Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: harmony-dev-unsubscribe@incubator.apache.org
For additional commands, e-mail: harmony-dev-help@incubator.apache.org


Re: Re: [equinox-dev] buddy classloading & deadlock

Posted by Pavel Pervov <pm...@gmail.com>.
Alex,

At DRLVM we developed the following rules for holding synchronization
primitives:
1) Never hold any native synchronization primivite while calling to java
from the VM;
2) Never hold any synchronization primitive while calling to user code
(especially class loaders) from the VM.

As far as I may observe, we strictly followed these rules up to now.

I wonder if it is posible to reproduce the scenario, described in the
forwarded mail, on Harmony running Eclipse...

Regards,
    Pavel Pervov.
Intel Middleware Products Division.

On 8/4/06, Alex Blewitt <al...@gmail.com> wrote:
>
> This message came up on equinox-dev recently. It highlights a
> potential deadlock when the Sun VM locks the classloader prior to
> calling loadClassInternal. I have no idea if this is an issue for the
> VM we're using, but if it is, we ought to consider what can be done to
> fix it.
>
> Alex.
>
> ---------- Forwarded message ----------
> From: Thomas Watson
> Date: 03-Aug-2006 16:32
> Subject: Re: [equinox-dev] buddy classloading & deadlock
> To: Equinox development mailing list
>
>
>
> What vendor/version of the VM are you using?
>
> There has been a long standing bug open against Sun on a similar
> issue.  It all boils down to the native VM locking the classloader
> before loading a class from it using the ClassLoader.loadClassInternal
> method.  In your stacktrace below this happens when the VM calls
> ClassLoader.loadClassInternal
> (DefaultClassLoader(ClassLoader).loadClassInternal(String) line: 319).
> The VM locks the classloader in native code before it ever calls into
> the ClassLoader.  This leaves us with no options, even if we override
> the loadClassInternal method to make it non-synchronized it will make
> no difference because the native code locks the ClassLoader no matter
> what the method signature is for loadClassInternal.  I have been told
> that Sun plans to fix this in a future release of the VM, it may be
> fixed in the latest 1.5 Sun VM.  The IBM VMs have fixed this issue,
> they will NOT lock the classloader before invoking it from the native
> VM code.
>
> Tom
>
> ---
>
> Hi all,
>
> I noticed that multithreading combined with buddy classloading can
> produce some scary deadlocks. I had one in a project last week and
> managed to recreate it in a toy example. Now I'm wondering if this is
> just one of the dangers of breaking the classloading hierarchy or if
> the framework could do something to avoid this ?
>
> My toy example (also in attachment):
>
> The main project has just one Application class:
>
> public class Application implements IPlatformRunnable{
>
>                 public Object run(Object args) throws Exception {
>                                  new Activator();
>                                  return true;
>                 }
>
> }
>
>
> and the dependent project has an Activator
>
> public class Activator implements BundleActivator {
>
> public void start(BundleContext context) throws Exception {
> new Thread(new Runnable() {
>                 public void run() {
>                 try {
>                    Class.forName("main.Application");
>                } catch (ClassNotFoundException e) { }
> }).start();
>
> // let other thread run to induce deadlock
> try { Thread.sleep(100); } catch (InterruptedException e) {}
> }
>
> public void stop(BundleContext context) throws Exception {}
>
> }
>
>
> The main project depends on dependent, and the dependent project has a
> global buddy policy.
>
>
> This causes the following deadlock:
>
> Thread [main] (Suspended)
>                 owns: DefaultClassLoader  (id=16)
>                 waiting for: DefaultClassLoader  (id=15)
>                 ClasspathManager.findLocalClassImpl(String,
> ClassLoadingStatsHook[]) line: 422
>                 ClasspathManager.findLocalClass(String) line: 410
>                 DefaultClassLoader.findLocalClass(String) line: 188
>                 BundleLoader.findLocalClass(String) line: 339
>                 SingleSourcePackage.loadClass(String) line: 37
>                 BundleLoader.findClass(String, boolean) line: 388
>                 BundleLoader.findClass(String) line: 352
>                 DefaultClassLoader.loadClass(String, boolean) line:
> 83
>                 DefaultClassLoader(ClassLoader).loadClass(String)
> line: 251
>
> DefaultClassLoader(ClassLoader).loadClassInternal(String) line: 319
>                 Application.run(Object) line: 11
>                 PlatformActivator$1.run(Object) line: 78
>                 EclipseAppLauncher.runApplication(Object) line: 92
>                 EclipseAppLauncher.start(Object) line: 68
>                 EclipseStarter.run(Object) line: 400
>                 EclipseStarter.run(String[], Runnable) line: 177
>                 NativeMethodAccessorImpl.invoke0(Method, Object,
> Object[]) line: not
> available [native method]
>                 NativeMethodAccessorImpl.invoke(Object, Object[])
> line: 39
>                 DelegatingMethodAccessorImpl.invoke(Object, Object[])
> line: 25
>                 Method.invoke(Object, Object...) line: 585
>                 Main.invokeFramework(String[], URL[]) line: 336
>                 Main.basicRun(String[]) line: 280
>                 Main.run(String[]) line: 977
>                 Main.main(String[]) line: 952
>
> Thread [Thread-1] (Suspended)
>                 owns: DefaultClassLoader  (id=15)
>                 waiting for: DefaultClassLoader  (id=16)
>                 ClasspathManager.findLocalClassImpl(String,
> ClassLoadingStatsHook[]) line: 422
>                 ClasspathManager.findLocalClass(String) line: 410
>                 DefaultClassLoader.findLocalClass(String) line: 188
>                 BundleLoader.findLocalClass(String) line: 339
>                 BundleLoader.findClass(String, boolean) line: 391
>                 BundleLoader.findClass(String) line: 352
>                 DefaultClassLoader.loadClass(String, boolean) line:
> 83
>                 DefaultClassLoader(ClassLoader).loadClass(String)
> line: 251
>                 BundleLoader.loadClass(String) line: 276
>                 BundleHost.loadClass(String, boolean) line: 227
>                 BundleHost(AbstractBundle).loadClass(String) line:
> 1245
>                 GlobalPolicy.loadClass(String) line: 39
>                 PolicyHandler.doBuddyClassLoading(String) line: 138
>                 BundleLoader.findClass(String, boolean) line: 402
>                 BundleLoader.findClass(String) line: 352
>                 DefaultClassLoader.loadClass(String, boolean) line:
> 83
>                 DefaultClassLoader(ClassLoader).loadClass(String)
> line: 251
>
> DefaultClassLoader(ClassLoader).loadClassInternal(String) line: 319
>                 Class<T>.forName0(String, boolean, ClassLoader) line:
> not available
> [native method]
>                 Class<T>.forName(String) line: 164
>                 Activator$1.run() line: 12
>                 Thread.run() line: 595
> [attachment "buddy-classloading-deadlock.zip" deleted by Thomas
> Watson/Austin/IBM] _______________________________________________
> equinox-dev mailing list
> https://dev.eclipse.org/mailman/listinfo/equinox-dev
>
>
> _______________________________________________
> equinox-dev mailing list
> https://dev.eclipse.org/mailman/listinfo/equinox-dev
>
> ---------------------------------------------------------------------
> Terms of use : http://incubator.apache.org/harmony/mailing.html
> To unsubscribe, e-mail: harmony-dev-unsubscribe@incubator.apache.org
> For additional commands, e-mail: harmony-dev-help@incubator.apache.org
>
>