Skip to content

Commit

Permalink
Ease ClassLoader Deadlocks Where Possible
Browse files Browse the repository at this point in the history
When on Java 7 we can register the classloader as parallel capable to prevent deadlocks caused by certain scenarios. Due to the nature of PluginClassLoader this isn't completely safe, but we can make it safer by switching to concurrency focused collections. Either way this is far better than crashing the server.
  • Loading branch information
md-5 authored and SpigotMC committed Sep 4, 2014
1 parent 72bcf60 commit b2b8924
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
public final class JavaPluginLoader implements PluginLoader {
final Server server;
private final Pattern[] fileFilters = new Pattern[] { Pattern.compile("\\.jar$"), };
private final Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
private final Map<String, Class<?>> classes = new java.util.concurrent.ConcurrentHashMap<String, Class<?>>(); // Spigot
private final Map<String, PluginClassLoader> loaders = new LinkedHashMap<String, PluginClassLoader>();
public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot

Expand Down
26 changes: 25 additions & 1 deletion src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,38 @@
*/
final class PluginClassLoader extends URLClassLoader {
private final JavaPluginLoader loader;
private final Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
private final Map<String, Class<?>> classes = new java.util.concurrent.ConcurrentHashMap<String, Class<?>>(); // Spigot
private final PluginDescriptionFile description;
private final File dataFolder;
private final File file;
final JavaPlugin plugin;
private JavaPlugin pluginInit;
private IllegalStateException pluginState;

// Spigot Start
static
{
try
{
java.lang.reflect.Method method = ClassLoader.class.getDeclaredMethod( "registerAsParallelCapable" );
if ( method != null )
{
boolean oldAccessible = method.isAccessible();
method.setAccessible( true );
method.invoke( null );
method.setAccessible( oldAccessible );
org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.INFO, "Set PluginClassLoader as parallel capable" );
}
} catch ( NoSuchMethodException ex )
{
// Ignore
} catch ( Exception ex )
{
org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.WARNING, "Error setting PluginClassLoader as parallel capable", ex );
}
}
// Spigot End

PluginClassLoader(final JavaPluginLoader loader, final ClassLoader parent, final PluginDescriptionFile description, final File dataFolder, final File file) throws InvalidPluginException, MalformedURLException {
super(new URL[] {file.toURI().toURL()}, parent);
Validate.notNull(loader, "Loader cannot be null");
Expand Down

0 comments on commit b2b8924

Please sign in to comment.