8

I'm running into the strangest error in this program, which is confirmed when debugging it. I have the following code (boiled down to highlight the problem, of course):

BHFrame.java

public class BHFrame
{
  private boolean uSS;
  private StateSaver stateSaver;

  public BHFrame(boolean useInternalStateSaver)
  {
    //Init code

    uSS = useInternalStateSaver;

    //More init code
    System.out.println(uSS);
    if (uSS)
    {System.out.println("Entered 1");
      stateSaver = new StateSaver(title, false);
      stateSaver.addSaveable(getThis());
    }

    //More init code
    System.out.println(uSS);
    if (uSS)
    {System.out.println("Entered 2");
      try
      {
        stateSaver.loadState();
        stateSaver.putState(getThis());
      }
      catch (IOException ex)
      {
        alertUserOfException(ex);
      }
    }
  }
}

GUI.java

public class GUI extends BHFrame
{
  public GUI(boolean useInternalStateSaver)
  {
    super(useInternalStateSaver);
  }
}

Main.java

public class Main
{
  public static void main(String[] args)
  {
    GUI gui = new GUI(false);
  }
}

Output

false
false
Entered 2
Exception in thread "main" java.lang.NullPointerException
    at bht.tools.comps.BHFrame.<init>(BHFrame.java:26)
    at bhms.GUI.<init>(GUI.java:5)
    at bhms.Main.main(Main.java:5)

The class BHFrame is extended and run from a child class that calls this constructor, but that really shouldn't affect this behavior. The problem is that, when false is passed to the constructor as useInternalStateSaver, the first if (uSS) is skipped, but the second is entered. Upon debugging, I found that uSS is false throughout runtime, including on the line of the second if statement, here. Why would Java enter an if statement when the condition returns false? Before you ask, I did delete the .class files and recompile it just in case there was some residual code messing with it, but I got the same result. And rest assured, all the references to the uSS variable are displayed here.

Solution


As it turns out, this appears to be a bug in NetBeans 7.1 Build 201109252201, wherein the IDE doesn't properly insert new code into the compiled .class files. The problem was fixed by compiling the files externally. A bug report has been submitted.

Charles
  • 50,943
  • 13
  • 104
  • 142
Ky -
  • 30,724
  • 51
  • 192
  • 308
  • 7
    `if` condition won't make wrong decisions. your variable `uSS` must become true in your `//More init code` line. – Raptor Nov 03 '11 at 03:21
  • It isn't. Something else is going on. – Brian Roach Nov 03 '11 at 03:21
  • Could you add in the code that occurs at the `//More init code` part? – Mansoor Siddiqui Nov 03 '11 at 03:22
  • I think my latest edit shows that it's not what's going on there. Plus, the `//More init code` part doesn't interact with the `uSS` variable. – Ky - Nov 03 '11 at 03:27
  • I'm sure uSS must be changed at some point in your code. It is not the problem with JVM or java compiler. Since you have done the debugging, you should have found out where it has become true yourself. – gigadot Nov 03 '11 at 03:27
  • What happens if you print `uSS` at the beginning of the inside of your `try{}` block? –  Nov 03 '11 at 03:28
  • Look, I confirmed with the debugger that `uSS` is always `false`. It is never `true`, not even when entering the second `if` block – Ky - Nov 03 '11 at 03:30
  • Can you format the code using netbean format function? just to make sure that your braces are correct. – gigadot Nov 03 '11 at 03:36
  • I... did? My NetBeans formatting preferences are reflected perfectly int he provided code. – Ky - Nov 03 '11 at 03:38
  • 2
    The code you're debugging and the code you posted are different (and the code you posted doesn't compile because of bits you've deleted) - so it's possible that the issue is due to that. Everyone is telling you're wrong, because there is no way the code you've shown us can do what you're saying it does. But maybe the code you're actually running can do that. – Tim Nov 03 '11 at 03:38
  • Please provide an [sscce](http://sscce.org/) that exhibits the problem you describe. – trashgod Nov 03 '11 at 03:40
  • @trashgod I'm trying, but people keep demanding more and more... – Ky - Nov 03 '11 at 03:41
  • @Supuhstar most of those "demands" are coming about because of the lack of a SSCCE. But to be honest, I expect the answer you'll get after the SSCCE is going to be "works for me" – Tim Nov 03 '11 at 03:45
  • The art of the sscce is to provide less and less. When I comment out all the erroneous lines, I see nothing unexpected. – trashgod Nov 03 '11 at 03:49
  • @trashgod I initially posted only what they needed: The code in BHFrame that interacts with `uSS`. However, they continually asked for the code I left out – Ky - Nov 03 '11 at 03:57
  • 1
    What if you leave `uSS` unused and add a another private boolean and use that - what happens? And, if Java as optimizations, try turning them off if they're on? And what happens when the code is run outside of the debugger and outside of Netbeans? – Zabba Nov 03 '11 at 04:02
  • 1
    Your example _isn't_ self contained. The issue is that none of us can take the code, compile it, and reproduce the problem. I understand why you can't do that, but it also means that we can't actually help you. Your code looks fine, but it's incomplete (so we keep assuming the issue is in the code that we can't see) and it isn't standalone (so we can't see the issue for ourselves). Your best bet it to keep reducing it down until you get a piece of code that exhibits the issue, and only contains methods that you can post. Anything else is likely to keep going round in the same circles. – Tim Nov 03 '11 at 04:06
  • @Zabba +1 for the first constructive comment I've seen, here – Ky - Nov 03 '11 at 04:06
  • @Tim why can't you give a list of possible reasons that this can happen, eliminate all the ones that have to do with things I said I took care of (like changing the value of `uSS` somewhere), and posting the rest? – Ky - Nov 03 '11 at 04:08
  • 1
    This may be stupid but try stable version of Netbeans. SInce none of us can see the problem, we can only make assumption for you to try. – gigadot Nov 03 '11 at 04:09
  • 1
    Also try printing the value of `useInternalStateSaver` along side the value of `uSS` you are already printing. And also try using `useInternalStateSaver` directly instead of assigning to `uSS` and using that (set the uSS at the end of the method instead of near the beginning) – Zabba Nov 03 '11 at 04:10
  • @gigadot Thank you for your idea. I am now downloading the last stable release. – Ky - Nov 03 '11 at 04:10
  • You could also try using a different version of the JDK than what you're using now (try 1.7 and 1.5 if you're using 1.6 for example) – Zabba Nov 03 '11 at 04:12
  • Another suggestion is that if you delete the class files yourself using windows explorer, can you try to use Netbean clean function to clean it and you should try to restart your Netbeans. (if the problem disappear, it maybe the bug in Netbeans) – gigadot Nov 03 '11 at 04:12
  • @Zabba Post "what happens when the code is run outside of the debugger and outside of Netbeans?" as an answer, because it runs fine outside NetBeans – Ky - Nov 03 '11 at 04:12
  • Also, how is it that `GUI gui = new GUI(false);` is not giving an error (unless you do have a ctor with one parameter as well). Could it be that that other ctor is calling the `BHFrame` ctor too - and thus the code is running from a different entry point than what you are thinking it is? – Zabba Nov 03 '11 at 04:14
  • @Zabba sorry, I never updated the Main.java code... look again – Ky - Nov 03 '11 at 04:14

3 Answers3

1

Whatever's throwing that exception is probably not in your posted code.

It's not being caught by your catch statement, which only catches IOException.

It's a NullPointerException and can occur anywhere.

You have shown no indication that the code inside your if block is actually executing. In your screenshot, there is absolutely know way of knowing if your if block is entered or not. There are no logging statements.

Add debugging messages at various points to see exactly what is happening. Or, you know, look at line 26 (wayyyyy before your posted code) to see why you're getting a NullPointerException.

  • but it shouldn't have entered the if statement in the first place. Since "Enter 2" text is printed, it means the block is executed. – gigadot Nov 03 '11 at 03:39
  • 1
    +1 just for pointing out that the screenshot proves the code doesn't match the error output – Tim Bender Nov 03 '11 at 03:50
  • Another edit adds a screenshot with the output after debugging to the next line from the first screenshot – Ky - Nov 03 '11 at 04:03
0

I've seen crazy stuff like this when there is bad RAM on the machine. You might want to run memtest86.

You might also consider deleting all of your project class files, and then doing a build. Maybe you changed Main.java, but it was never recompiled. I hate that when that happens.

BillRobertson42
  • 12,602
  • 4
  • 40
  • 57
  • 1
    I states int he question that I deleted all my `.class` files, and why would bad RAM affect this one `boolean` value, but leave the rest of the 4294967288 bytes perfectly fine? And even if it is the case, wouldn't that mean that it would run fine the next time, as `uSS` will be stored in a different address? – Ky - Nov 03 '11 at 03:34
  • If you don't think its the RAM, then what other explanation do you have for this apparent non-deterministic behavior? I was responsible for a project that saw 15,000 JVMs deployed across the country. There were machines that we would deploy to where the JVM would not behave correctly, where other software appeared to. After replacing the RAM on these machines, the problems went away. Memtest86 is free so there is no cost in trying it. The only other option is that you're doing something wrong, and you're not aware of what that is. – BillRobertson42 Nov 04 '11 at 00:32
  • please don't post such comments without reading the full question (which includes the reason) and accepted answer – Ky - Nov 06 '11 at 17:47
  • Yeah, I saw the answer up there after responding. I didn't know that it could be added like that. Wasn't sure if I should have deleted my comment or not. i.e. don't know the site's etiquette. – BillRobertson42 Nov 07 '11 at 01:42
  • The best thing to do in that case would be to add another comment that retracts what you want to retract, so that any legitimate usable information you posted is still there to be learned. – Ky - Nov 07 '11 at 03:50
  • 1
    Thanks for the feedback, and sorry I missed that. – BillRobertson42 Nov 08 '11 at 00:30
0

This is just a guess, because I can't see the code you are mentioning, but I reckon you have defined a local variable uSS in the second //More init code segment.

Once you define a local variable named the same as an instance variable, it 'hides' the instance variable. Better to qualify all instance variables with this.

So, try qualifying all above accesses of uSS with this. ... (this.uSS)

Even if this isn't the issue, it might be better to post the full code anyway.

HTH

laher
  • 8,860
  • 3
  • 29
  • 39
  • 1
    Also, it would be good to mark the instance variable as `final`. It seems like it ought to be. Again, this would provide clarity if not anything else – laher Nov 03 '11 at 03:35
  • see edit; there is a screenshot showing that what I claim is really what is happening. I am no novice programmer; I know when I make variables what they do (that's why the class variable `uSS` isn't called `useInternalStateSaver`: to guarantee I'm referencing the right variable) – Ky - Nov 03 '11 at 03:36
  • Also, I am hesitant to post the full code, as it is not only copyrighted, but also very extensive. I will if I get enough demand, but I guarantee you that this is all you need to see. – Ky - Nov 03 '11 at 03:37
  • ok, but for clarity it's better to post code with qualified accessors and final variables where appropriate. It helps people to help you .. – laher Nov 03 '11 at 03:40
  • I've posted as much as I'm comfortable with – Ky - Nov 03 '11 at 03:56
  • That's really good, but (I know I'm repeating myself) you still haven't qualified your accessors or marked your instance variable as private. i.e. `if(this.uSS) {` and `private final boolean uSS;`. It may come to nothing but honestly it would remove several doubts for those who are trying to help you. I'm off now, good luck – laher Nov 03 '11 at 04:21
  • 1
    p.s. I just upvoted your question, because clearly you're trying hard to engage with your [doubtful] audience. I see you found the solution too. Nice one – laher Nov 03 '11 at 04:25
  • 1
    it came to nothing. As I mentioned before, I am no novice programmer, and `uSS` was never changed after it was first initialized, and I was referencing the same variable each time. However, it was not, as most respondents assumed, bad coding, but rather a bug in the IDE's debugger. – Ky - Nov 03 '11 at 04:27
  • Dude I never meant to diss your prowess, so don't take offence from me - just trying to isolate some possibilities (although you took an onslaught from a few others!) – laher Nov 03 '11 at 04:29
  • sorry, I am just used to this community respecting the information I provide for them, and was severely taken aback when most of the responses didn't trust my analysis of my own problem – Ky - Nov 03 '11 at 04:32