-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Minor
-
None
-
Affects Version/s: None
Spoke to md_5 on IRC about getOfflinePlayer(String) not being thread-safe. If a method is blocking, it is supposed to be thread-safe otherwise he says it is considered to be a bug.
I wrote a simple plugin to observe failed attempts to invoke getOfflinePlayer() from multiple async tasks:
GetOfflinePlayerAsyncTest.java
package net.minelink.gopat; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.plugin.java.JavaPlugin; import java.util.UUID; public class GetOfflinePlayerAsyncTest extends JavaPlugin { @Override public boolean onCommand(final CommandSender sender, Command command, String label, String[] args) { for (int i = 0; i < 3; ++i) { Bukkit.getScheduler().runTaskLaterAsynchronously(this, new Runnable() { @Override public void run() { Bukkit.getOfflinePlayer(UUID.randomUUID().toString().substring(0, 15)); } }, 1); } return true; } }
Invoking the above code will produce one of three outcomes:
- It will simply work
- It will throw a ConcurrentModificationException
- It will throw a NullPointerException
The stack traces observed in the console are as follows:
ConcurrentModificationException
[23:55:17 WARN]: Exception in thread "Craft Scheduler Thread - 0" [23:55:17 WARN]: org.apache.commons.lang.UnhandledException: Plugin GetOfflinePlayerAsyncTest v0.0.1-SNAPSHOT generated an exception while executing task 28 at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:56) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: java.util.ConcurrentModificationException at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:953) at java.util.LinkedList$ListItr.next(LinkedList.java:886) at com.google.common.collect.Iterators$9.next(Iterators.java:939) at com.google.common.collect.Iterators.addAll(Iterators.java:357) at com.google.common.collect.Lists.newArrayList(Lists.java:147) at net.minecraft.server.v1_8_R1.UserCache.a(UserCache.java:213) at net.minecraft.server.v1_8_R1.UserCache.c(UserCache.java:194) at net.minecraft.server.v1_8_R1.UserCache.getProfile(UserCache.java:123) at org.bukkit.craftbukkit.v1_8_R1.CraftServer.getOfflinePlayer(CraftServer.java:1288) at org.bukkit.Bukkit.getOfflinePlayer(Bukkit.java:741) at net.minelink.gopat.GetOfflinePlayerAsyncTest$1.run(GetOfflinePlayerAsyncTest.java:19) at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftTask.run(CraftTask.java:71) at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)
NullPointerException
[23:55:22 WARN]: Exception in thread "Craft Scheduler Thread - 3" [23:55:22 WARN]: org.apache.commons.lang.UnhandledException: Plugin GetOfflinePlayerAsyncTest v0.0.1-SNAPSHOT generated an exception while executing task 35 at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:56) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.NullPointerException at java.util.LinkedList$ListItr.next(LinkedList.java:891) at com.google.common.collect.Iterators$9.next(Iterators.java:939) at com.google.common.collect.Iterators.addAll(Iterators.java:357) at com.google.common.collect.Lists.newArrayList(Lists.java:147) at net.minecraft.server.v1_8_R1.UserCache.a(UserCache.java:213) at net.minecraft.server.v1_8_R1.UserCache.c(UserCache.java:194) at net.minecraft.server.v1_8_R1.UserCache.getProfile(UserCache.java:123) at org.bukkit.craftbukkit.v1_8_R1.CraftServer.getOfflinePlayer(CraftServer.java:1288) at org.bukkit.Bukkit.getOfflinePlayer(Bukkit.java:741) at net.minelink.gopat.GetOfflinePlayerAsyncTest$1.run(GetOfflinePlayerAsyncTest.java:19) at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftTask.run(CraftTask.java:71) at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)
- is duplicated by
-
SPIGOT-914 Failed to handle packet ConcurrentModificationException & ArrayIndexOutOfBoundsException
-
- Closed
-
Any update to this? Still an on-going issue with 1.8.6.
Spigot 1.8.6 git-Spigot-6a6b839-b0e81a4
ChestShop v3.8.8
Also occasionally occurs with EnjinMinecraftPlugin v2.7.2 at startup.