Java Forum / General / October 2005
ExceptionInInitializerError: NullPointerException
Shin - 29 Sep 2005 01:26 GMT If you have time, take a look at this trace I got (see below). Basically, my code tries to export a RMI object. The weird thing is that through disassembly, the class XXX doesn't even have static initialization code to run., but nonetheless, the trace says it's because when executing initilization code for XXX, a NullPointerException occurred.
Any suggestions of how I might proceed from here are welcome.
java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:164) at YYY_Stub.class$(Unknown Source) at YYY_Stub.<clinit>(Unknown Source) at sun.misc.Unsafe.ensureClassInitialized(Native Method) at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:25) at sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:122) at java.lang.reflect.Field.acquireFieldAccessor(Field.java:917) at java.lang.reflect.Field.getFieldAccessor(Field.java:898) at java.lang.reflect.Field.getLong(Field.java:527) at java.io.ObjectStreamClass.getDeclaredSUID(ObjectStreamClass.java:1559) at java.io.ObjectStreamClass.access$600(ObjectStreamClass.java:47) at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:381) at java.security.AccessController.doPrivileged(Native Method) at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:373) at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:268) at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:504) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1546) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1460) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1693) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:339) at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source) at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:375) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240) at sun.rmi.transport.Transport$1.run(Transport.java:153) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:149) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701) at java.lang.Thread.run(Thread.java:595) Caused by: java.lang.NullPointerException at XXX.<clinit>(dist.java:134)
-Shin
puzzlecracker - 29 Sep 2005 03:16 GMT > If you have time, take a look at this trace I got (see below). > Basically, my code tries to export a RMI object. The weird thing is [quoted text clipped - 53 lines] > Caused by: java.lang.NullPointerException > at XXX.<clinit>(dist.java:134) intersting script.. I dont think rmi is well supported on the mac. You shouldn't run rmi on the mac in the first place, talk to mac people - they should know it.
I would strongly suggest to start learning c++
Roedy Green - 29 Sep 2005 05:08 GMT >If you have time, take a look at this trace I got (see below). >Basically, my code tries to export a RMI object. The weird thing is >that through disassembly, the class XXX doesn't even have static >initialization code to run., but nonetheless, the trace says it's >because when executing initilization code for XXX, a >NullPointerException occurred. in that case, decompile/disassemble the code to see what the static init in doing. See http://mindprod.com/jgloss/decompiler.html or http://mindprod.com/jgloss/disassembler.html
In RMI there are stub objects generated. Perhaps that is what you are looking at or perhaps something being reported that happened at the other end of the wire.
I am just guessing here, but that looks much like the sort of thing you would see if you were reconstituting a serialised stream where the code on the sending and receiving end is not in sync. A class is missing or different at the receiving end. If you have not been assigning serialVerisonUIDs to all your serialisable classes, consider doing that. It cuts down on this sort of thing and also makes it easier to track the problems.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Shin - 29 Sep 2005 18:04 GMT Thanks, but the code is only trying to export a RMI object. There is no client code running whatsoever in the test.
Different versions of classes? NO. I will consider the 'serialVersonUID' tip, thanks.
> In RMI there are stub objects generated. Perhaps that is what you are > looking at or perhaps something being reported that happened at the [quoted text clipped - 7 lines] > consider doing that. It cuts down on this sort of thing and also makes > it easier to track the problems. -Shin
Roedy Green - 29 Sep 2005 22:06 GMT >Thanks, but the code is only trying to export a RMI object. There is >no client code running whatsoever in the test. What do you mean by that? Where is the object going?
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Shin - 30 Sep 2005 18:37 GMT I meant I haven't started the client VM yet, or no code has yet tried to connect to the RMI object for the trace I showed.
> >Thanks, but the code is only trying to export a RMI object. There is > >no client code running whatsoever in the test. [quoted text clipped - 3 lines] > Canadian Mind Products, Roedy Green. > http://mindprod.com Again taking new Java programming contracts. Thomas Hawtin - 29 Sep 2005 11:31 GMT > If you have time, take a look at this trace I got (see below). > Basically, my code tries to export a RMI object. The weird thing is > that through disassembly, the class XXX doesn't even have static > initialization code to run., but nonetheless, the trace says it's > because when executing initilization code for XXX, a > NullPointerException occurred. Sure? I don't think one should be inserted anywhere, particularly with a reference to a source file and line number.
> Caused by: java.lang.NullPointerException > at XXX.<clinit>(dist.java:134) Do you want to tell us what is on line 134 of dist.java?
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Shin - 29 Sep 2005 18:13 GMT > Sure? I don't think one should be inserted anywhere, particularly with a > reference to a source file and line number. Didn't follow.
> > Caused by: java.lang.NullPointerException > > at XXX.<clinit>(dist.java:134) > > Do you want to tell us what is on line 134 of dist.java? Yeah, I have been examined that quite thoroughly. It's an initialization to an static field, _ff_, by calling a method on another class's static field, _gg_ (which is initialized lazily at runtime, but by the time, the RMI object is exported, it should have been initialized (I tested by put it in a static initialization block)). I also made _gg_ volatile, just in case.
The thing that I don't understand is that why the RMI server thread attempts to initialiaze XXX. It's not reference in any way in the RMI object class YYY. Does the RMI server initialize all the Serializable class at startup? I don't think it should be.
-Shin
Thomas Hawtin - 29 Sep 2005 21:06 GMT > [Shin wrote: ] > [quoted text clipped - 9 lines] > initialized (I tested by put it in a static initialization block)). I > also made _gg_ volatile, just in case. It's an exception when the class description is being read. It hasn't got to the actual object yet. Possibly that isn't important.
Code outside of class initialisation should not have threading problems caused by half-initialised classes. Indeed that is a standard idiom for lazy loading (one that actually works too).
My guess is that you have a cyclic dependency in your class initialisation.
> The thing that I don't understand is that why the RMI server thread > attempts to initialiaze XXX. It's not reference in any way in the RMI > object class YYY. Does the RMI server initialize all the Serializable > class at startup? I don't think it should be. In general you can't find all Serializable objects, as ClassLoader doesn't support that. It seems there is some reason why the stub of YYY need an XXX class object.
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Roedy Green - 30 Sep 2005 04:54 GMT >It's an exception when the class description is being read. It hasn't >got to the actual object yet. Possibly that isn't important. one other little factoid to throw into the mix
If the class you are loading throws an Exception during the static initialisation, it will show up as a NoClassDefFoundException rather than the original Exception, which your code may not be prepared to handle.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Shin - 30 Sep 2005 18:55 GMT The problem somehow disappeared, after I checkouted a clean copy and run it elsewhere, and changed the version of rmiregistry I run.
It's so unsatisfying to not see this error got pinned down. I am sure it's not a classpath problem since I examined the running commandline and everything is specified there (and environment variable).
Anyway, thanks for all the discussions.
> It's an exception when the class description is being read. It hasn't > got to the actual object yet. Possibly that isn't important. > > Code outside of class initialisation should not have threading problems > caused by half-initialised classes. Indeed that is a standard idiom for > lazy loading (one that actually works too). Agreed. The volatile on static fields is not necessary.
> My guess is that you have a cyclic dependency in your class initialisation. No.
> > The thing that I don't understand is that why the RMI server thread > > attempts to initialiaze XXX. It's not reference in any way in the RMI [quoted text clipped - 4 lines] > doesn't support that. It seems there is some reason why the stub of YYY > need an XXX class object. -Shin
Shin - 30 Sep 2005 19:33 GMT > > Code outside of class initialisation should not have threading problems > > caused by half-initialised classes. Indeed that is a standard idiom for > > lazy loading (one that actually works too). > > > Agreed. The volatile on static fields is not necessary. Actually, it's a little inaccurate. Since the static field is lazily initialized, it's possible that a write to the field is not see by another thread that has already started. However, since like I said, the RMI export (and hence the RMI server thread) is after the initialization code to the field, in the same thread, there should not be such a problem. But static initializer is another matter, like you said.
[Truth might be all this is far away from what caused my original exception.]
-Shin
Shin - 01 Oct 2005 20:03 GMT [It's kind of silly, but I feel I owe you guys an explanation what really happened.]
It's no mystery after all, I found the cause.
When you try to export an object, the rmiregistry (in a different VM) will try to load the class in the RMI method signature, reflectively. If the class it tries to load has an eagerly initialized static field which depends on another class's lazily initialized field. Then you have a problem. One thing to notice is that it doesn't matter in the rmiregistry's VM what value the problematic static field is initialized to; once the method call is forwarded to the proper serving RMI objects, all is well in that VM.
Morale: 1. the rmiregistry might want to know too much; 2. mixing lazy and eager initialization shoudl be done with care.
> The problem somehow disappeared, after I checkouted a clean copy and > run it elsewhere, and changed the version of rmiregistry I run. -Shin
Roedy Green - 01 Oct 2005 20:21 GMT >When you try to export an object, the rmiregistry (in a different VM) >will try to load the class in the RMI method signature, reflectively. You mean dynamically, with classForName, right?. There is no dynamic construction of a class stub is there? There is something vaguely in the back of my mind that something profoundly changed in the way RMI works since I used it back in the 90s.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Shin - 07 Oct 2005 17:01 GMT > >When you try to export an object, the rmiregistry (in a different VM) > >will try to load the class in the RMI method signature, reflectively. [quoted text clipped - 3 lines] > the back of my mind that something profoundly changed in the way RMI > works since I used it back in the 90s. Like reference of YYY.class.
Roedy Green - 01 Oct 2005 20:23 GMT >If the class it tries to load has an eagerly initialized static field >which depends on another class's lazily initialized field. Can you explain the mechanism of the problem is a little more depth?
I could see a big problem if class A used class B's lazily initialised static that did not initialise until a B object was created, but that would be a bug always, not just when RMI were involved.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Shin - 07 Oct 2005 17:03 GMT > >If the class it tries to load has an eagerly initialized static field > >which depends on another class's lazily initialized field. [quoted text clipped - 4 lines] > static that did not initialise until a B object was created, but that > would be a bug always, not just when RMI were involved. It doesn't depend on allocating objects of B. But, if the initialization of B's static field depends on executing from "main" method (normally, it's the case), you got the same effect.
-Shin
Roedy Green - 08 Oct 2005 07:09 GMT >It doesn't depend on allocating objects of B. But, if the >initialization of B's static field depends on executing from "main" >method (normally, it's the case), you got the same effect. That's just a bug if you ever instantiate the class by any means other than calling main.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Roedy Green - 29 Sep 2005 22:07 GMT >> Sure? I don't think one should be inserted anywhere, particularly with a >> reference to a source file and line number. > >Didn't follow. If you post a stack trace, you also have to post the corresponding source code. Since source code listings on newsgroups don't come with line numbers, you have to point out interesting places in the code where the stack trace or error message is pointing for others to make sense of the stack trace.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Shin - 30 Sep 2005 18:38 GMT > >> Sure? I don't think one should be inserted anywhere, particularly with a > >> reference to a source file and line number. [quoted text clipped - 6 lines] > where the stack trace or error message is pointing for others to make > sense of the stack trace. Thanks.
Roedy Green - 29 Sep 2005 22:15 GMT >The thing that I don't understand is that why the RMI server thread >attempts to initialiaze XXX. Ah ha. Now you see why, at least when debugging, you should not do any suspect, complex initialisation in static init blocks. Make it an explicit call at least temporarily so you can track problems in it. This really pays off when you start single stepping.
If you are wondering why your class got loaded unexpectedly do this
static { new Throwable().printStackTrace(); }
for fancier stacktraces see http://mindprod.com/jgloss/trace.html
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|