Object getting garbage ;(

Discussion in 'Spigot Plugin Development' started by Benliam12, Jul 23, 2018.

  1. Ok, I made a mini (very small) plugin where Game instances were stored in a GameManager.

    (Using an ArrayList<Game>)

    Thing is, when I leave my server (that's running h24) well, when I come back, everything got garbage. I can't join any of my games unless I reload the server.

    Is there a simple way to prevent this from happening ?
     
  2. Fix your code? I'm sorry but objects you create don't magically change their values over time.
     
    • Agree Agree x 1
  3. Yes they do my friends ;) It's called Java Garbage Collection.

    Next time, you might magically have a good solution.
     
  4. Mind sharing some code? And an issue? You can't join the game for what reason exactly?
     
  5. https://github.com/Benliam12/Maze

    Before saying anything, I know, I'm using threads instead of BukkitRunnable to do my countdowns. I'm just too lazy to change it ;)
    Also, most of this code is like 3 years old, I just digged up into my old project.

    I can't join game after a moment because I get a Null pointer Exception (Exception I didn't get when server freshly started/reloaded
     
  6. That's not how the JVM's garbage collection works, the GC doesn't use a scheduled deallocator anymore. So I doubt garbage collection is the issue here. However, if you really think that garbage collection is your problem, it's simply because the heap isn't big enough causing the GC to deallocate memory in a certain block to free memory.

    TLDR; Tune your JVM's heap size properly if you really think it's the garbage collection, but you should definitely ask yourself whether this is the actual problem and not your own code.
     
    • Agree Agree x 2
  7. I guess this might be in my code. But at no point I'm removing my Object from my ArrayList so why, after a while would they return null when I try to get them ?
     
  8. For real, share us the real issue? I can't join the game isn't an issue we can help you with. Share the error stacktrace and even better give us more details.

    If you join a game multiple times in a short time does it actually break like it does if you were to do the same but a bit longer?
     
  9. Since I don't have the time to go over your entire code, but from a quick check and you saying you're using multiple threads to handle your games, my suggestion is to switch over to a concurrent solution where needed. For example, change your ArrayList<Game> to a CopyOnWriteArrayList<Game>.
     
  10. Even if it was garbage collection, tuning the heap size won't help. GC won't touch any objects which are strongly referenced somewhere. If it was the heap size which ran out, the JVM would OOM.
    Because you insert null most likely.

    Like darklazerog said, share the exception so we can see which part of the code is to blame.
     
    • Like Like x 1
    • Agree Agree x 1
  11. What will this do ?

    Also, I'm using a single Thread to handle all my countdowns.

    Simple, I get a Null PointerException after my server runs for more than 6h (longest delay I saw this happening). Also, as I mention, for the 2-3hrs I'm on the server, nothing happends. It's when I leave it that after a while things start to bug.

    Code (Text):
    Error occurred while disabling Maze v1.1.2b (Is it up to date?)
    java.lang.NullPointerException: null
    at org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer.teleport(CraftPlayer.java:526) ~[gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at org.bukkit.craftbukkit.v1_12_R1.entity.CraftEntity.teleport(CraftEntity.java:271) ~[gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at ca.benliam12.hub.Utils.TeleportUtil.toHub(TeleportUtil.java:36) ~[?:?]
    at ca.benliam12.hub.Hub.toHub(Hub.java:32) ~[?:?]
    at ca.benliam12.maze.game.Game.stop(Game.java:203) ~[?:?]
    at ca.benliam12.maze.game.GameManager.stop(GameManager.java:55) ~[?:?]
    at ca.benliam12.maze.Maze.onDisable(Maze.java:79) ~[?:?]
    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:266) ~[gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at org.bukkit.plugin.java.JavaPluginLoader.disablePlugin(JavaPluginLoader.java:361) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at org.bukkit.plugin.SimplePluginManager.disablePlugin(SimplePluginManager.java:422) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at org.bukkit.plugin.SimplePluginManager.disablePlugins(SimplePluginManager.java:415) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at org.bukkit.plugin.SimplePluginManager.clearPlugins(SimplePluginManager.java:456) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at org.bukkit.craftbukkit.v1_12_R1.CraftServer.reload(CraftServer.java:719) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at org.bukkit.Bukkit.reload(Bukkit.java:525) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:27) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at org.bukkit.craftbukkit.v1_12_R1.CraftServer.dispatchCommand(CraftServer.java:648) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at net.minecraft.server.v1_12_R1.PlayerConnection.handleCommand(PlayerConnection.java:1397) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at net.minecraft.server.v1_12_R1.PlayerConnection.a(PlayerConnection.java:1232) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at net.minecraft.server.v1_12_R1.PacketPlayInChat.a(PacketPlayInChat.java:45) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at net.minecraft.server.v1_12_R1.PacketPlayInChat.a(PacketPlayInChat.java:1) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at net.minecraft.server.v1_12_R1.PlayerConnectionUtils$1.run(SourceFile:13) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_45-internal]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_45-internal]
    at net.minecraft.server.v1_12_R1.SystemUtils.a(SourceFile:46) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at net.minecraft.server.v1_12_R1.MinecraftServer.D(MinecraftServer.java:748) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at net.minecraft.server.v1_12_R1.DedicatedServer.D(DedicatedServer.java:406) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at net.minecraft.server.v1_12_R1.MinecraftServer.C(MinecraftServer.java:679) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:577) [gbinvl_minecraft_spigot_1_12_2.jar:git-Spigot-2086bb0-1988d7f]
    at java.lang.Thread.run(Thread.java:745) [?:1.8.0_45-internal]
     
  12. How come then, when server is just started I don't get any null exceptions?
     
  13. Are you actually using weak references as these can be removed and so you need to know what you are doing when using them. Other then that the CG will *not* free objects (and thus recycle the memory which held them) as long as you have a reference to them (unless there a a bug in the JVM which is rather unlikely).
     
  14. it doesn't even happen in your maze plugin, but in your hub plugin.
    Because I assumed it was the problem as you described it. But instead it's a completely different problem.
     
  15. Doesn't the GC start from a GC root? Whether the root is strong, weak or phantom doesn't matter, if a reachable and referenced object from the root is out of scope of the root and there is not enough memory it still gets collected by the GC. Otherwise it makes no sense to grow the heap size when there is not enough memory. All though it would never collect the root, it still collects other references in the same chain. (as far as I know).
     
  16. All right, here is my Hub plugin : https://github.com/Benliam12/Hub

    This time I have no clue why it would send a NullPointerException since I (in case no location is set) put a default location in it.
     
  17. When A is an object is strongly referenced, there's a chain of strong references all the way to the JVM held objects or the main method, which strongly references A (so a normal reference, not weak, soft or phantom).

    A will never be GC'd, regardless of how the heap looks, while it's strongly referenced.

    If any object in that chain, let's name it B, is no longer strongly referenced (i.e. the 'parent' of B set the field that stored B to null in case of an instance field), all objects between B and A will no longer be strongly referenced, and thus be eligible to be collected by GC to free up memory.
     
  18. That's literally what I said yeah. So I don't get how growing the heap size has no effect on a situation where references do in fact get collected, whether they are in eden or tenure doesn't matter anymore(at this point). Growing the size of the heap makes it so that the GC doesn't have to deallocate memory, so I don't get your point?
     
  19. The world is null. Could be that it hasn't loaded yet (if it's not set to world)
    GC will never deallocate the object if it's actually referenced. If he didn't set it to null, it's there and GC won't touch it.

    That's why tuning the size doesn't matter: it only 'configures' when GC will run (in a weak way, GC implementation has all control of when exactly it runs), but doesn't affect what will be GC'd.
     
    • Like Like x 1
  20. Plugins works fine until a certain amount of time where I'm offline. This mean, the world isn't null and is fully loaded since, well, its working after the server is started.