Index: /trunk/src/org/openstreetmap/josm/plugins/PluginClassLoader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginClassLoader.java	(revision 12322)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginClassLoader.java	(revision 12322)
@@ -0,0 +1,60 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Class loader for JOSM plugins.
+ * <p>
+ * In addition to the classes in the plugin jar file, it loads classes of required
+ * plugins. The JOSM core classes should be provided by the the parent class loader.
+ * @since 12322
+ */
+public class PluginClassLoader extends URLClassLoader {
+
+    Collection<PluginClassLoader> dependencies;
+
+    static {
+        ClassLoader.registerAsParallelCapable();
+    }
+
+    /**
+     * Create a new PluginClassLoader.
+     * @param urls URLs of the plugin jar file (and extra libraries)
+     * @param parent the parent class loader (for JOSM core classes)
+     * @param dependencies class loaders of required plugin; can be null
+     */
+    public PluginClassLoader(URL[] urls, ClassLoader parent, Collection<PluginClassLoader> dependencies) {
+        super(urls, parent);
+        this.dependencies = dependencies == null ? new ArrayList<>() : new ArrayList<>(dependencies);
+    }
+
+    /**
+     * Add class loader of a required plugin.
+     * This plugin will have access to the classes of the dependent plugin
+     * @param dependency the class loader of the required plugin
+     */
+    public void addDependency(PluginClassLoader dependency) {
+        dependencies.add(dependency);
+    }
+
+    @Override
+    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+        for (PluginClassLoader dep : dependencies) {
+            try {
+                Class<?> result = dep.loadClass(name, resolve);
+                if (result != null) {
+                    return result;
+                }
+            } catch (ClassNotFoundException e) {}
+        }
+        Class<?> result = super.loadClass(name, resolve);
+        if (result != null) {
+            return result;
+        }
+        throw new ClassNotFoundException(name);
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 12321)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 12322)
@@ -290,7 +290,8 @@
 
     /**
-     * Global plugin ClassLoader.
-     */
-    private static DynamicURLClassLoader pluginClassLoader;
+     * Class loader to locate resources from plugins.
+     * @see #getJoinedPluginResourceCL()
+     */
+    private static DynamicURLClassLoader joinedPluginResourceCL;
 
     /**
@@ -709,26 +710,42 @@
 
     /**
-     * Get the class loader for loading plugin code.
+     * Method to get the (now obsolete) class loader for loading plugin code.
      *
      * @return the class loader
-     */
+     * @deprecated There is no longer a unified plugin class loader. Use {@link PluginProxy#classLoader}
+     * to get the class loader for each plugin. Or <code>PluginClass.class.getClassLoader()</code>
+     * to access the class loader from within the plugin.
+     */
+    @Deprecated
     public static synchronized DynamicURLClassLoader getPluginClassLoader() {
-        if (pluginClassLoader == null) {
-            pluginClassLoader = AccessController.doPrivileged((PrivilegedAction<DynamicURLClassLoader>)
+        return getJoinedPluginResourceCL();
+    }
+
+    /**
+     * Get class loader to locate resources from plugins.
+     *
+     * It joins URLs of all plugins, to find images, etc.
+     * (Not for loading Java classes - each plugin has a separate {@link PluginClassLoader}
+     * for that purpose.)
+     * @return class loader to locate resources from plugins
+     */
+    private static synchronized DynamicURLClassLoader getJoinedPluginResourceCL() {
+        if (joinedPluginResourceCL == null) {
+            joinedPluginResourceCL = AccessController.doPrivileged((PrivilegedAction<DynamicURLClassLoader>)
                     () -> new DynamicURLClassLoader(new URL[0], Main.class.getClassLoader()));
-            sources.add(0, pluginClassLoader);
-        }
-        return pluginClassLoader;
-    }
-
-    /**
-     * Add more plugins to the plugin class loader.
-     *
-     * @param plugins the plugins that should be handled by the plugin class loader
-     */
-    public static void extendPluginClassLoader(Collection<PluginInformation> plugins) {
+            sources.add(0, joinedPluginResourceCL);
+        }
+        return joinedPluginResourceCL;
+    }
+
+    /**
+     * Add more plugins to the joined plugin resource class loader.
+     *
+     * @param plugins the plugins to add
+     */
+    private static void extendJoinedPluginResourceCL(Collection<PluginInformation> plugins) {
         // iterate all plugins and collect all libraries of all plugins:
         File pluginDir = Main.pref.getPluginsDirectory();
-        DynamicURLClassLoader cl = getPluginClassLoader();
+        DynamicURLClassLoader cl = getJoinedPluginResourceCL();
 
         for (PluginInformation info : plugins) {
@@ -754,5 +771,5 @@
      * @param pluginClassLoader the plugin class loader
      */
-    public static void loadPlugin(Component parent, PluginInformation plugin, ClassLoader pluginClassLoader) {
+    private static void loadPlugin(Component parent, PluginInformation plugin, PluginClassLoader pluginClassLoader) {
         String msg = tr("Could not load plugin {0}. Delete from preferences?", plugin.name);
         try {
@@ -760,5 +777,5 @@
             if (klass != null) {
                 Main.info(tr("loading plugin ''{0}'' (version {1})", plugin.name, plugin.localversion));
-                PluginProxy pluginProxy = plugin.load(klass);
+                PluginProxy pluginProxy = plugin.load(klass, pluginClassLoader);
                 pluginList.add(pluginProxy);
                 Main.addAndFireMapFrameListener(pluginProxy);
@@ -808,9 +825,38 @@
                 return;
 
-            extendPluginClassLoader(toLoad);
+            Map<PluginInformation, PluginClassLoader> classLoaders = new HashMap<>();
+            for (PluginInformation info : toLoad) {
+                classLoaders.put(info, new PluginClassLoader(
+                        info.libraries.toArray(new URL[0]),
+                        Main.class.getClassLoader(),
+                        null));
+            }
+
+            // resolve dependencies
+            for (PluginInformation info : toLoad) {
+                PluginClassLoader cl = classLoaders.get(info);
+                DEPENDENCIES:
+                for (String depName : info.getRequiredPlugins()) {
+                    for (PluginInformation depInfo : toLoad) {
+                        if (depInfo.getName().equals(depName)) {
+                            cl.addDependency(classLoaders.get(depInfo));
+                            continue DEPENDENCIES;
+                        }
+                    }
+                    for (PluginProxy proxy : pluginList) {
+                        if (proxy.getPluginInformation().getName().equals(depName)) {
+                            cl.addDependency(proxy.getClassLoader());
+                            continue DEPENDENCIES;
+                        }
+                    }
+                    throw new AssertionError("unable to find dependency " + depName + " for plugin " + info.getName());
+                }
+            }
+
+            extendJoinedPluginResourceCL(toLoad);
             monitor.setTicksCount(toLoad.size());
             for (PluginInformation info : toLoad) {
                 monitor.setExtraText(tr("Loading plugin ''{0}''...", info.name));
-                loadPlugin(parent, info, getPluginClassLoader());
+                loadPlugin(parent, info, classLoaders.get(info));
                 monitor.worked(1);
             }
@@ -1162,5 +1208,5 @@
         for (PluginProxy plugin : pluginList) {
             if (plugin.getPluginInformation().name.equals(name))
-                return plugin.plugin;
+                return plugin.getPlugin();
         }
         return null;
Index: /trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 12321)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 12322)
@@ -316,12 +316,14 @@
      *
      * @param klass the plugin class
+     * @param classLoader the class loader for the plugin
      * @return the instantiated and initialized plugin
      * @throws PluginException if the plugin cannot be loaded or instanciated
-     */
-    public PluginProxy load(Class<?> klass) throws PluginException {
+     * @since 12322
+     */
+    public PluginProxy load(Class<?> klass, PluginClassLoader classLoader) throws PluginException {
         try {
             Constructor<?> c = klass.getConstructor(PluginInformation.class);
             Object plugin = c.newInstance(this);
-            return new PluginProxy(plugin, this);
+            return new PluginProxy(plugin, this, classLoader);
         } catch (ReflectiveOperationException e) {
             throw new PluginException(name, e);
Index: /trunk/src/org/openstreetmap/josm/plugins/PluginProxy.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginProxy.java	(revision 12321)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginProxy.java	(revision 12322)
@@ -22,5 +22,6 @@
      * The plugin.
      */
-    public final Object plugin;
+    private final Object plugin;
+    private final PluginClassLoader classLoader;
 
     /**
@@ -28,8 +29,29 @@
      * @param plugin the plugin
      * @param info the associated plugin info
+     * @param classLoader the class loader for the plugin
+     * @since 12322
      */
-    public PluginProxy(Object plugin, PluginInformation info) {
+    public PluginProxy(Object plugin, PluginInformation info, PluginClassLoader classLoader) {
         super(info);
         this.plugin = plugin;
+        this.classLoader = classLoader;
+    }
+
+    /**
+     * Get the plugin object.
+     * @return the plugin object
+     * @since 12322
+     */
+    public Object getPlugin() {
+        return plugin;
+    }
+
+    /**
+     * Get the class loader for the plugin.
+     * @return the plugin class loader
+     * @since 12322
+     */
+    public PluginClassLoader getClassLoader() {
+        return classLoader;
     }
 
