• Post Reply Bookmark Topic Watch Topic
  • New Topic

ExceptionInInitializerError  RSS feed

 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Posting this to make a public record of a bug that was a real challenge for me to solve today, partly because I couldn't find much about it online.

Here's a SSCCE that makes the bug happen at run-time:

Running it produces this stack dump:
Exception in thread "main" java.lang.ExceptionInInitializerError
	at enumfail.Main.main(Main.java:7)
Caused by: java.lang.NullPointerException
	at enumfail.Dumper.(Main.java:29)
	at enumfail.Constant.(Main.java:19)
	at enumfail.Constant.(Main.java:13)
	... 1 more
Part of why this was hard for me to debug is that, in my actual code, the NullPointerException at Line 29 doesn't appear as the second line of the dump. It appears dozens of lines farther down. Typically, I look at the first line of a dump to see where the problem is. Here, though, it directs me to Line 7, and is complaining about an ExceptionInInitializerError. Well, the problem isn't really at Line 7. It's at Line 29, where an attempt to use the enumerated type value CONSTANT is made.

Recall that the enum class's constructor is implicitly called for each value when the enum is loaded, which happens the first time any use of the enum is made. That happens here at Line 7. There is only one value, defined at Line 13. The constructor is called for that value, which calls the constructor for the Dumper class, at Line 19. That call attempts to use the value CONSTANT, which is still null at this point, because its constructor hasn't yet returned. So, the real problem is not at Line 7. It's at Line 29, where an attempt is made to use a not fully constructed instance of the Constant enum is taking place. The solution might be to defer the creation of the Dumper object to some time after the Constant constructor returns.

Somewhat inelegantly, this fixes the problem: The output this time is merely:
CONSTANT
This is, perhaps, akin to the warnings you get when passing this out of constructors. Interestingly, this code: runs fine, with this output:
enumfail.Constant@5c647e05
enumfail.Constant@5c647e05
Further, while there is a "leaking this in constructor" warning at Line 18, there is no such warning at Line 17. I'd be curious to know if anyone can explain that.

Note that the code below generates a compile-time error: At Line 13, you get, "illegal reference to static field from initializer." I am guessing this is also akin to the error you get at Line 9 in this code: At Line 9, the compiler complains that, "variable X might not have been initialized." And note that the earlier complaint, "illegal reference to static field from initializer" (now at Line 19), uses the word "initializer," not "constructor," which, I think, says something about how enums work.

Anyway, that's a lesson I learned today. ExceptionInInitializerErrors can be caused by attempting to reference an enumerated value from code that is run while the value's constructor is executing, and has not yet returned.
 
Junilu Lacar
Sheriff
Posts: 11485
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Circular references tend to create problems like this. I'd question the design before looking for a workaround like that. Why does the Constant enum need to have a reference to the Dumper class anyway?
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:Circular references tend to create problems like this. I'd question the design before looking for a workaround like that. Why does the Constant enum need to have a reference to the Dumper class anyway?

To make the bug happen. 

In the actual product, I have a singleton that is a data model. To avoid creating multiple instances of the view that edits the model, the singleton creates it and sets it visible when the controller asks to edit the model. The model doesn't know anything about the view, other than how to create it and make it visible. The view needs to be able to access the model, of course, so that's why there are mutual references.

I could do it with a wrapper class that holds a reference to the model and to the view, and have that create the view and manage its visibility. I've done it that way before, but it adds a level of indirection that just confuses me. It's worth doing when there might be any number of instances of the model, and each could be open for editing, but you still don't want any instance of the model open in more than one editor at a time. Here, where my model is a singleton, it seems easy enough to just have it create and open/close its one editor itself.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!