Solved Strange Null Pointer

Discussion in 'Plugin Development' started by xtechgamer735, Sep 23, 2014.

Thread Status:
Not open for further replies.
  1. fireblast709 The code at the NPE (Line 45/15 in paste) is:
    Code:java
    1. if (plugin.getConfig().getBoolean("spawningArmour"))


    Would my main class help?

    Thanks again,
     
  2. Offline

    fireblast709

    xtechgamer735 Could you paste the stacktrace and the classes mentioned by the stacktrace?
     
  3. Offline

    Hawktasard

  4. Yep.
     
  5. Offline

    xize

    xtechgamer735

    could I ask when did you write to the file and when did you tried to get the value from that config, you are sure you saved it and reloaded that config again?

    what I geuss what could be a problem is that Yaml or aka your config is using a memory version which is not up to date with the file being saved or nothing has been writed to the file than just the memory version of it.

    so to make my geuss better I demostrate it cus it may sound a bit weird and confusing, and yes this is psuodo:

    Code:
    private FileConfiguration con;
    private FileConfiguration con2;
     
    public void onEnable() {
           File f = new File(this.getDataFolder(), "config.yml");
           if(f.exists()) {
                 //just ignore this one
                 this.con = this.getConfig();
           } else {
                //look what happens here.
               this.con = this.getConfig();
                this.con2 = this.getConfig();
                this.con2.set("bla", 1);
                this.saveConfig(); //or this.getConfig().save(); don't know how this is used:P
          
               }
    }
     
    public int getBla() {
            return con.getInt("bla");
    }
    
    what happens is that you could have 2 different memory versions of the configuration as fields, so when you use 'con' as return in the getBla() method there could be a chance that the whole key does not exist because it doesn't exist in the memory variant, when you use con2 there is a chance it works fine.

    I don't know how it works in plugin.getConfig() and plugin.saveConfig() and plugin.reloadConfig(), but if those methods return a new memory version of the memory configuration each time rather than reuse the same instance over and over again, then this could be the issue, to fix this you need to re load the file on the memory version.

    I hope it gives you a idea though. ;-)
     
  6. Offline

    fireblast709

    Can't cause a NPE :p.
     
  7. Offline

    xize

    fireblast709

    ah yea you are right, just looked how the getBoolean() method is used in the MemorySection and theres no throw new NullPointerException() so then it should be false when null:p
     
  8. Offline

    adam753

    37 posts? Disappointed in all of you!
    Code:
    public class Main extends JavaPlugin implements Listener
    {
        Helmet HelmetObj = new Helmet(this);
        //etc
    
    When you initialise a variable in-line like this, it will be set the moment Java loads the class. That's fine for things like ints, but when it involves method calls, you want to be very wary. In this case, Helmet's constructor tries to do plugin.getConfig(), but the plugin doesn't have a config yet because Java has only just started up, Bukkit probably hasn't done anything yet. Create the new Helmet in onEnable and it should work fine.
     
  9. Offline

    ZachBora

    adam753 This is what happens when devs wait 2 pages before sharing code and only share 1 line at a time.
    What adam753 said is true, you should initialize your variables in the onEnable, and if you wanted to be clean you should dispose of them in the onDisable.
     
  10. Offline

    fireblast709

    adam753 and I'm disappointed that you didn't know that class body variables are created when an instance is created. Your case would only hold with static variables. That aside, he invokes the method onCommand.
     
  11. adam753 Thanks, only bit I don't understand is how do I access it from outside the onEnable? It says it cannot be resolved.

    Code:java
    1. public void onEnable()
    2. {
    3. Helmet HelmetObj = new Helmet(this);
    4. }
    5.  
    6. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
    7. {
    8. Player p = (Player) sender;
    9. if (args[0].equalsIgnoreCase("helmet"))
    10. {
    11. HelmetObj.actionHelmet(p); //Error, can not be resolved
    12.  
    13. return true;
    14. }
     
  12. Offline

    fireblast709

    xtechgamer735 not that the suggested fix should matter, but I don't intend to be close minded:

    Create a Helmet field (and leave it uninitialised). Then initialise it in onEnable.
    Code:Java
    1. private Helmet helmetObj;
    2.  
    3. public void onEnable()
    4. {
    5. helmetObj = new Helmet(this);
    6. }
     
  13. Offline

    ZachBora

    fireblast709 What would be your suggestion aside from using the onEnable?
     
  14. Offline

    fireblast709

    ZachBora atm I'm out of clues. It could be IDE cache, or using reloads as well.
     
  15. Offline

    ZachBora

    fireblast709 Well the variable was initialized in the Main class, before the plugin was loaded, so it was null in the Helmet constructor. I don't see another way around this.
     
  16. Offline

    fireblast709

    ZachBora 'this' can never be null. That would imply that you are inside a nonexistant object ಠ_ಠ
     
  17. fireblast709 I still can't get it to work, I'm at a loss with what to do. Only thing I can think of is handling the commands in the new class and making it implement CommandExecutor. Think that would work?
     
  18. Offline

    fireblast709

    xtechgamer735 post all (yes, all!) the code you have. A separate CommandExecutor would not solve this issue.
     
  19. Offline

    ZachBora

    fireblast709 'this' isn't null. The pastes are gone, but I remember that inside the helmet constructor he was doing like plugin.getConfig() which would be where he was setting the null property.

    xtechgamer735
    Please don't declare a variable inside a class with the same name as the class :|
    Helmet variable inside Helmet class.

    Edit: I'm trying to help with the issue but all your stacktrace pastes are now gone. Which line is causing the NPE?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 14, 2016
  20. Offline

    ZachBora

    xtechgamer735 I'm still looking, but I noticed another thing. You have code for when the player is leaving. Please note that there is a high chance that when the server is closed, that event is not called for every player (if called at all). I know that Glowstone does not call the player leave event, did not verify this with bukkit so I couldn't say.

    Just something to take into account.

    Edit: I don't think the error paste is in sync with the github repository. Main.java:248 is "this.reloadConfig();". I suspect it should be "HelmetObj.actionHelmet(p);". Since this is wrong I can't be sure what Helmet.java:45 represents.
     
  21. ZachBora The Main is a bit out but helmet class is fine. Thanks for your help so far!
     
  22. Offline

    fireblast709

    That was 'if(plugin.getConfig().getBoolean("path"))' inside the class body. This wouldn't even compile, so it's safe to assume he doesn't have it in the class body :p.

    xtechgamer735 In the case that you use /reload, try an actual restart. Also, it might be that your IDE has an old cached class, so try clearing it's cache (for Maven it's "mvn clean [additional goals, like 'package']"). The latter can also be verified if you decompile your jar to check if the code that is being packed in the jar is outdated (JD-GUI is probably one of the easiest methods for this)
     
  23. Offline

    adam753

    fireblast709 Out of interest, I still think my answer was right. getConfig() returns a reference to JavaPlugin's newConfig field, which Bukkit sets (along with some other fields) after creating an instance of your plugin object. But he was indirectly calling getConfig() from an in-line variable assignment in Main, which would have been done before the constructor or anything else.

    For reference: https://github.com/Bukkit/Bukkit/blob/master/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
     
  24. Offline

    fireblast709

    adam753 If you read that line carefully (but it seems his hastebin expired, so don't trouble yourself searching for it), you would've noticed a compile-time error: he was using an if-statement there. This pretty much gives you two options: OP was being nooby or it was a combination of lines in one paste. The first seemed unlikely since he was already testing the plugin (thus it had to compile), so it was the latter.

    But even if he was able to run it on that point, your answer would've been wrong. For that, you need to follow the logic a bit further then you did:
    • JavaPlugin#getConfig() would check if newConfig is null. If so, it invokes JavaPlugin#reloadConfig()
    • JavaPlugin#reloadConfig() invokes YamlConfiguration#loadConfiguration(File)
    • YamlConfiguration#loadConfiguration(File) invokes Validate.notNull(Object, String) on the first line
    If you invoke getConfig() before the initialization (with File being null), it will not return null. No, in fact, 'good guy Bukkit' is pretty verbose and throws you a neat IllegalArgumentException instead of an 'arbitrary' NullPointerException.

    and as a funfact: you can actually do stuff right after you invoke super() in your no arg constructor (if you have one)!
     
Thread Status:
Not open for further replies.

Share This Page