6

On start up, my program immediately throw an ExceptionInInitializerError. The source is from this method:

public static void errorMessage(String input) {
    System.err.println("[ERROR] " + form.format(date) + " - " + Thread.currentThread().getStackTrace()[3].getClassName() + ": " + input);
}

I printed out the different parts of the string and found that the error is only thrown when I call form.format(date). It says it is null. The only problem is, both date and form are statically declared right above this method as so:

public static Date date = new Date();
public static DateFormat form = new SimpleDateFormat("HH:mm:ss");

The error suddenly started being thrown after some minor bug fixing. I have no idea what is wrong or how something could be wrong with this. I mean, I am calling on statically declared variables in the same class. Technically, they should not be null, yet they are. Anyone have any ideas why it is throwing this error? Here is the console output:

java.lang.ExceptionInInitializerError
at A$$OpSystem.getOperatingSystem(A$.java:98)
at A_.<clinit>(A_.java:19)
Caused by: java.lang.NullPointerException
at A$.errorMessage(A$.java:72)
at A$.loadCursor(A$.java:84)
at A$.<clinit>(A$.java:62)
... 2 more
Exception in thread "main" 

By the way, A$.OpSystem.getOperatingSystem is only being shown there because it calls A$.errorMessage...

And I have had this problem before, it was just when a statically declared variable was actually never declared an remained null when it was called. Now it is not supposed to be null, yet it is. So I have no idea what is causing it. Ideas?

But I guess this is a good time to be educated on how static variables actually load...

EDIT: It seems as though no exception is thrown if I move the static Cursor object that calls 'loadCursor' to a different class. What?

I made a test of this situation but it returns no error?

public class StaticMethodTesting {

public static int i = getInt();

public static int getInt() {
    return getAnotherInt();
}

public static int getAnotherInt() {
    return 0;
}

public static void main(String[]args) {
    System.out.println("Hi");
}
}
Dave Newton
  • 158,873
  • 26
  • 254
  • 302
CoderTheTyler
  • 839
  • 2
  • 11
  • 30
  • 1
    Can you show more code? Can you paste an [SSCCE](http://sscce.org)? – obataku Aug 15 '12 at 03:09
  • Would you like to post the entire class? – Vikdor Aug 15 '12 at 03:10
  • Yes or a snippet that reproduces the problem. – Jacob Schoen Aug 15 '12 at 03:10
  • I really cannot seem to reproduce the problem. It is just that 'date' and 'form' are null. When I print them out, they return null. And nothing else in 'errorMessage' returns null. So how would a statically declared variable be null if it was not declared null. – CoderTheTyler Aug 15 '12 at 03:17
  • I assume form and date are defined in the same class as the errorMessage() method? – Jacob Schoen Aug 15 '12 at 03:18
  • Yes they are in the same class – CoderTheTyler Aug 15 '12 at 03:20
  • Stupid question, could you have a cached version laying around? Or is someone else importing an older version of the Jar? (Had some one does this in our project, spent days tracking it down) – MadProgrammer Aug 15 '12 at 03:21
  • 1
    The only thing I could find so far is http://stackoverflow.com/questions/2547713/why-static-fields-are-not-initialized-in-time, but this is a static method and not a constructor, so it does not seem to apply. – Jacob Schoen Aug 15 '12 at 03:21
  • @MadProgrammer : What do you mean? All I did before this started happening was changed the name of a JFrame from gameFrame to frame. But where would I find said cached version? – CoderTheTyler Aug 15 '12 at 03:23
  • Without actually seeing your code it's impossible to tell you why this is happening. Static stuff happens in order (give or take), so something is calling that line before the fields are initialized. – Dave Newton Aug 15 '12 at 03:25
  • @MrDoctorProfessorTyler I know, sounds stupid. In netbeans I've run across this type of problem before, where it's internal cache is not been updated correctly. I don't know what you are using as your dev environment, but the same thing might be happening. Rather the rebuilding the classes, it's relying on a cached version. If you have multiple projects all working with the same library, some one might be referencing an older version, causing the wrong class to be loaded - I know, straw clutching, but we've tested everything else :P – MadProgrammer Aug 15 '12 at 03:26
  • 1
    Pssh... `SimpleDateFormat` is **not** threadsafe. It's absolutely not recommended to make it a class variable. Rather create it inside the local method scope instead. – BalusC Aug 15 '12 at 03:36
  • Haha! That is also a helpful thing to know although that wasn't the problem. Oh and thanks everybody for the help. @veer solved it! – CoderTheTyler Aug 15 '12 at 03:38
  • Of course, threadsafety problems don't occur if you're running with only one thread ;) – BalusC Aug 15 '12 at 03:50
  • Well yes :p But I used it a few times in multi threaded programs and the date sometimes didn't display correctly – CoderTheTyler Aug 15 '12 at 03:54
  • Oh and @jschoen, you were actually right about http://stackoverflow.com/questions/2547713/why-static-fields-are-not-initialized-in-time?lq=1 It had the same issue as my code – CoderTheTyler Aug 15 '12 at 04:08

2 Answers2

7

After examining your exception trace...

at A$.errorMessage(A$.java:72)
at A$.loadCursor(A$.java:84)
at A$.< clinit>(A$.java:62)

It becomes clear that some static field initialization in A$ is executing prior to the initialization of date and form and calling loadCursor, which then logically fails with NullPointerException as date and form are uninitialized.

The issue is that you've placed the the code which initializes your Cursor before that which initializes your date and form objects. Static fields with assignments at declaration time are initialized in declaration order, as per Section §8.3.2.1 of the Java Language Specification.

If you read the detailed initialization process, particularly Section §12.4.2.9, you find...

Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.


So, you're likely doing something like this:

static Cursor cursor = loadCursor();
static Date date = new Date();
static DateFormat form = new SimpleDateFormat("HH:mm:ss");

static Cursor loadCursor() {
  ...
  errorMessage("...");
  ...
}

loadCursor must not be called before date and form are initialized if you wish for this to work.


The reason your example produces no 'error' (huh?) is because neither method refer to a yet uninitialized field. If you want equivalent behavior which is in no way an error, see the following (which can be seen run here):

import java.util.Random;

public final class Example {

  /* note if the below read: static final int value = rand.nextInt(),
     this would be considered an illegal forward reference to rand */
  private static final int value = next();
  private static final Random rand = new Random();

  private static int next() {
    return rand.nextInt();
  }

  public static void main(final String[] argv) { }
}

The output can be seen to be as follows.

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
        at Example.next(Example.java:11)
        at Example.<clinit>(Example.java:7)
obataku
  • 29,212
  • 3
  • 44
  • 57
  • Right, but shouldn't they have been initialized before the static method actually ran? I thought it went top down doing static variables before it even ran the method for the first time. – Jacob Schoen Aug 15 '12 at 03:25
  • This is what I first thought the issue was. But the code which initializes the cursor is in a different class. How do static fields load between classes? Stupid question, does the compiler load the classes in alphabetical order or some other way which would cause one field to be loaded before another? EDIT: Yes I am calling something like that but the cursor is defined in an entirely different class which is why this doesn't make any sense. How do static fields load between classes? – CoderTheTyler Aug 15 '12 at 03:27
  • @veer And I learned something new today, I would have assumed that would not have compiled. I guess I did not read the JLS that closely back in school even though we had to for a class. – Jacob Schoen Aug 15 '12 at 03:32
  • 1
    Oh I think I understand now. I will try calling loadCursor after the method declaration – CoderTheTyler Aug 15 '12 at 03:34
  • 1
    Well, that is interesting. It solved the problem. I have never had this issue before though. Hmph... Oh well. Thanks for the solution! I think I am going to experiment a bit more with static fields now and see what I can and cannot do. – CoderTheTyler Aug 15 '12 at 03:37
  • @jschoen, no, if a static method is to be called to initialize a class variable, it is called right then prior to initializing those below it. – obataku Aug 15 '12 at 03:40
  • @veer: I made a test of this but it throws no error? Can you look above and see if I am duplicating it correctly? – CoderTheTyler Aug 15 '12 at 03:41
  • @MrDoctorProfessorTyler I advise you read the JLS while experimenting for an explanation of whatever behavior you come across. – obataku Aug 15 '12 at 03:41
  • Right, I was not considering calling a static method to initialize a static variable. If I had complex logic to initialize a static variable in the past, I always used a static block right after declaring the variable. – Jacob Schoen Aug 15 '12 at 03:42
  • 2
    @MrDoctorProfessorTyler, classes are initialized in the order in which dependencies are encountered in program execution, including class initialization. It starts with your main class. If this class has code that references class A, then A will start initialization. If this in turn references class B, then B's initialization will start. If B references A, code in A can run **before A is fully initialized**. This problem is caused by trying to do too much work in static initialization. – Stuart Marks Aug 15 '12 at 03:43
  • Ohhh. Ok that would make more sense. Thanks +1! – CoderTheTyler Aug 15 '12 at 03:45
  • 1
    @MrDoctorProfessorTyler The example you posted does not recreate the problem. Take a look at https://gist.github.com/3355609 to see an example that causes it. – Jacob Schoen Aug 15 '12 at 03:49
  • So would it always be more safe to declare static methods before static variables? And thanks @jschoen that is what I was looking for – CoderTheTyler Aug 15 '12 at 03:49
  • @MrDoctorProfessorTyler why would that example cause an error in your mind? Nothing there refers to a yet uninitialized field. Additionally, it does not matter where you declare static methods (though it *does* matter where you place static initializers). – obataku Aug 15 '12 at 03:53
  • 2
    @MrDoctorProfessorTyler I have updated my post to include a relevant simple example demonstrating the issue. – obataku Aug 15 '12 at 03:59
  • Thank you I understand why it does this now :D I love this community – CoderTheTyler Aug 15 '12 at 04:04
0

I think you'll find the problem is occurring here

Thread.currentThread().getStackTrace()[3].getClassName() 

You may need to do something more like

StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
String className = stackTrace[Math.min(3, stackTrace.length - 1)].getClassName();

Or similar :P

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366