Java 哈希图在一段时间不使用它们后会丢失



我遇到了一段时间后哈希图消失的问题。也就是说 - 当一个方法访问其中一个时,我会得到一个 NPE。如果我运行"刷新"方法来重新加载哈希图,一切正常。我的直觉告诉我,垃圾收集正在扫除这些,因为它们一次闲置数小时,甚至可能数天。

这就是我初始化它们的方式:

public static HashMap<Integer, Location> explorerLocations = new HashMap<Integer, Location>();
public static HashMap<Integer, Integer> explorerDifficulties = new HashMap<Integer, Integer>();
public static HashMap<Integer, Integer> explorerRewards = new HashMap<Integer, Integer>();
public static LinkedHashMap<Location, Integer> explorerLocationsReversed = new LinkedHashMap<Location, Integer>();
public static HashMap<Integer, String> explorerIDs = new HashMap<Integer, String>();
public static HashMap<Integer, Integer> explorerPrereqs = new HashMap<Integer, Integer>();

这就是我将它们加载到内存中的方式:

public static void syncExplorerLocations() {
int locCount = 0;
// reset the hashmap
RunicParadise.explorerLocations.clear();
RunicParadise.explorerDifficulties.clear();
RunicParadise.explorerRewards.clear();
RunicParadise.explorerLocationsReversed.clear();
RunicParadise.explorerIDs.clear();
RunicParadise.explorerPrereqs.clear();
// retrieve updated Explorer data
final Plugin instance = RunicParadise.getInstance();
MySQL MySQL = new MySQL(instance, instance.getConfig().getString("dbHost"),
instance.getConfig().getString("dbPort"), instance.getConfig().getString("dbDatabase"),
instance.getConfig().getString("dbUser"), instance.getConfig().getString("dbPassword"));
try {
final Connection d = MySQL.openConnection();
Statement dStmt = d.createStatement();
ResultSet explorerLocData = dStmt.executeQuery(
"SELECT * FROM rp_ExplorerLocations WHERE Status != 'Disabled' ORDER BY `Order` ASC;");
// if (!playerData.first() && !playerData.next()) {
if (!explorerLocData.isBeforeFirst()) {
// No results
// do nothing
d.close();
return;
} else {
// results found!
while (explorerLocData.next()) {
String[] locParts = explorerLocData.getString("Location").split("[\x2E]");
Location newLoc = new Location(Bukkit.getWorld(locParts[0]), Integer.parseInt(locParts[1]),
Integer.parseInt(locParts[2]), Integer.parseInt(locParts[3]));
RunicParadise.explorerLocations.put(explorerLocData.getInt("ID"), newLoc);
RunicParadise.explorerLocationsReversed.put(newLoc, explorerLocData.getInt("ID"));
RunicParadise.explorerDifficulties.put(explorerLocData.getInt("ID"),
explorerLocData.getInt("DifficultyRadius"));
RunicParadise.explorerRewards.put(explorerLocData.getInt("ID"),
explorerLocData.getInt("TokenReward"));
RunicParadise.explorerPrereqs.put(explorerLocData.getInt("ID"), explorerLocData.getInt("PreReq"));
RunicParadise.explorerIDs.put(explorerLocData.getInt("ID"),
explorerLocData.getString("LocationName"));
locCount++;
}
d.close();
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
"sc " + locCount + " explorer locs loaded into memory!");
}
} catch (SQLException z) {
Bukkit.getLogger().log(Level.SEVERE, "Failed map sync for explorer locs cuz " + z.getMessage());
}
}

那么,对于这里的专家来说 - 我的直觉是否正确,缺乏使用导致垃圾收集吞噬了这些?如果是这样,确保他们留在原地的最佳方法是什么?我能想到的就是定期刷新它们,但这听起来像是一种解决方法。

谢谢

====

添加其他信息。说真的,3个反对票?

[03:43:27] [ERROR]: null
org.bukkit.command.CommandException: Unhandled exception executing command 'explore' in plugin RunicParadise v0.1
at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[spigot.jar:git-Spigot-f950f8e-1c07d5c]
at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) ~[spigot.jar:git-Spigot-f950f8e-1c07d5c]
at org.bukkit.craftbukkit.v1_11_R1.CraftServer.dispatchCommand(CraftServer.java:649) ~[spigot.jar:git-Spigot-f950f8e-1c07d5c]
at net.minecraft.server.v1_11_R1.PlayerConnection.handleCommand(PlayerConnection.java:1335) [spigot.jar:git-Spigot-f950f8e-1c07d5c]
at net.minecraft.server.v1_11_R1.PlayerConnection.a(PlayerConnection.java:1170) [spigot.jar:git-Spigot-f950f8e-1c07d5c]
at net.minecraft.server.v1_11_R1.PacketPlayInChat.a(PacketPlayInChat.java:45) [spigot.jar:git-Spigot-f950f8e-1c07d5c]
at net.minecraft.server.v1_11_R1.PacketPlayInChat.a(PacketPlayInChat.java:1) [spigot.jar:git-Spigot-f950f8e-1c07d5c]
at net.minecraft.server.v1_11_R1.PlayerConnectionUtils$1.run(SourceFile:13) [spigot.jar:git-Spigot-f950f8e-1c07d5c]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_66]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_66]
at net.minecraft.server.v1_11_R1.SystemUtils.a(SourceFile:46) [spigot.jar:git-Spigot-f950f8e-1c07d5c]
at net.minecraft.server.v1_11_R1.MinecraftServer.D(MinecraftServer.java:739) [spigot.jar:git-Spigot-f950f8e-1c07d5c]
at net.minecraft.server.v1_11_R1.DedicatedServer.D(DedicatedServer.java:399) [spigot.jar:git-Spigot-f950f8e-1c07d5c]
at net.minecraft.server.v1_11_R1.MinecraftServer.C(MinecraftServer.java:675) [spigot.jar:git-Spigot-f950f8e-1c07d5c]
at net.minecraft.server.v1_11_R1.MinecraftServer.run(MinecraftServer.java:574) [spigot.jar:git-Spigot-f950f8e-1c07d5c]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_66]
Caused by: java.lang.NullPointerException
at io.github.runelynx.runicparadise.Commands.searchExplorerLocation(Commands.java:3752) ~[?:?]
at io.github.runelynx.runicparadise.Commands.onCommand(Commands.java:264) ~[?:?]
at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[spigot.jar:git-Spigot-f950f8e-1c07d5c]
... 15 more

。以及它所指的方法和行[行3752]....

public static Boolean searchExplorerLocation(Location loc, Player p) {
int targetID = 0;
int distance = -1;
Boolean noneFound = false;
int greenWarmthMultiplier = 2;
int yellowWarmthMultiplier = 4;
int redWarmthMultiplier = 6;
if (RunicParadise.explorerLocations.isEmpty()) {
// Just in case the map is empty -- load it up! This happened on
// 8/10/16 somehow. :-/
Commands.syncExplorerLocations();
}
for (Location l : RunicParadise.explorerLocations.values()) {
**[NPE THROWN HERE] if (l.getWorld().getName().equals(loc.getWorld().getName())) {**
// Make sure worlds match before taking distance
if ((distance != -1 && loc.distance(l) < distance) || (distance == -1)) {
// Compare with last distance. The idea is to only retain
// the closest distance loc via this loop.
distance = (int) loc.distance(l);
targetID = RunicParadise.explorerLocationsReversed.get(l);
}
}
}
if (targetID != 0) {
// A distance & loc were found, so let's run our logic.
int difficulty = RunicParadise.explorerDifficulties.get(targetID);
if (distance <= difficulty) {
// found location!
completePlayerExploration(targetID, p);
playNBS(p, "ZeldaSecret");
} else if (distance <= greenWarmthMultiplier * difficulty) {
// Green OK!
TitleAPI.sendFullTitle(p, 1, 2, 1, ChatColor.GREEN + "✸ ✸ ✸",
ChatColor.DARK_GREEN + "You are very close to a secret spot!");
p.sendMessage(ChatColor.DARK_GREEN + "You are very close to a secret spot!");
} else if (distance <= yellowWarmthMultiplier * difficulty) {
// Yellow OK!}
TitleAPI.sendFullTitle(p, 1, 2, 1, ChatColor.YELLOW + "✸ ✸ ✸",
ChatColor.GOLD + "You are kinda close to a secret spot!");
p.sendMessage(ChatColor.GOLD + "You are kinda close to a secret spot!");
} else if (distance <= redWarmthMultiplier * difficulty) {
// Red OK!
TitleAPI.sendFullTitle(p, 1, 2, 1, ChatColor.RED + "✸ ✸ ✸",
ChatColor.DARK_RED + "There is a secret spot in your general area!");
p.sendMessage(ChatColor.DARK_RED + "There is a secret spot in your general area!");
} else {
noneFound = true;
}
} else {
noneFound = true;
}
if (noneFound) {
TitleAPI.sendFullTitle(p, 1, 2, 1, ChatColor.AQUA + "✕ ✕ ✕",
ChatColor.DARK_AQUA + "There are no secret spots nearby!");
p.sendMessage(ChatColor.DARK_AQUA + "There are no secret spots nearby!");
}
return false;
}
for (Location l : RunicParadise.explorerLocations.values()) {
**[NPE THROWN HERE] if (l.getWorld().getName().equals(loc.getWorld().getName())) {**

所以这里没有空的一件事是HashMapexplorerLocations。否则,您将在调用HashMap.values()的前一行上获得 NPE。

ll.getWorld()l.getWorld().getName()locloc.getWorld()中的任何一个都可以为空。

你吠错了树。

最新更新