JavaRanch » Java Forums »
Java »
Swing / AWT / SWT
| Author |
Tricky NullPointerException Problem
|
colin shuker
Ranch Hand
Joined: Apr 11, 2005
Posts: 712
|
|
Hi, I've got a problem with my image handling in an application. It works perfectly fine on my pc, but on my friends pc, there is a NullPointerException happening when it tries to use: createLargeImages(String folder) <--- Loads 6 Large images in for each face of cube createSmallImages(int W) <--- Splits each of the 6 large images into 9 small ones The point is, these two methods work fine when he uses the button to load in a new set of 6 large images, its just the first call to them (in Main class constructor) that gives a NullPointerException I'm thinking the createSmallImages(int W) is possibly being called before the createLargeImages(String folder) completes, resulting in the exception Basically, after I jar the application, there is an "images" folder(in same directory as jar file), the images folder contains several subfolders (any names can be used for these folders, these names become JMenuItems) Below is the Main class: And the Images class is here: Sorry for the big amount of code, but I thought I should include it for clarity. If anyone can understand why I get a NullPointerException (see ** in Main class) that would be great. Thanks for any advice. [ April 08, 2007: Message edited by: colin shuker ]
|
 |
Campbell Ritchie
Sheriff
Joined: Oct 13, 2005
Posts: 32704
|
|
Please post the whole stack trace. I am not at all convinced you have got the location of the NullPointerException right. This problem is so common I think there ought to be a NullPointerException FAQ . NullPointerExceptions occur in certain circumstances:-When you have declared an object and not instantiated it.When you have "lost" an object, maybe a transient field which has been serialised and not reconstructed on de-serialisation.You have mistakenly set an object equal to nullYou have mistakenly passed a null reference when an object is called for.When you say "throw new NullPointerException();" or similar.And there are probably others. There is no way you can have a null reference in a line likeCheck for everything I have suggested in the list. Get the highest line you can find where the stack trace shows something you have written yourself. Find every object mentioned in that line/statement. If you have access to a debugger, put a breakpoint on that line, and when you get there inspect every object mentioned in the line, to make sure it is not null. If you don't have a debugger, count all the objects mentioned in that line, and insert a line rather like this immediately before it:-Make sure every object you can see in that line is included. If you get a printout of something incomprehensible, assume you actually have an object there. If it is null, it will say "Object 3 = null". If that doesn't work, go up the stack trace to an earlier line and repeat the whole procedure. Where have you instantiated your largeImages[] and subImages[] arrays?
|
 |
Campbell Ritchie
Sheriff
Joined: Oct 13, 2005
Posts: 32704
|
|
|
. . . and please confirm that your friend has the images in the correct folder for your app to find.
|
 |
colin shuker
Ranch Hand
Joined: Apr 11, 2005
Posts: 712
|
|
My friend has images in correct folder, because when he clicks on a button, he can load which ever set of 6 images he wants, using those 2 methods: createLargeImages, createSmallImages. So thats not the problem, its the first call in the constructor to call these 2 methods to load them in. I've used try catch blocks, and the NPE is coming from createSmallImages code, but I don't know why. I can't print a stack trace or anything, because there is no error on my pc, just on his, he doesn't understand java, or have an IDE, I just send him the jar files, and he runs them, the only way I know the NPE is coming from there is because I have got the details to show up on a JLabel, but this is extremely tedious and frustrating trying to fix a problem that you don't have by running it on someone elses computer by displaying the error through the GUI. Thats why I'm having to ask at the forum, is this a threading issue? Perhaps I need to use SwingUtilities.invokeAndWait(Runnable runnable), but I have tried it a couple of ways, and its still causing an error. The largeImages and subImages are instantiated each time createLargeImages and createSmallImages are called. Any more ideas? Thanks [ April 08, 2007: Message edited by: colin shuker ]
|
 |
Craig Wood
Ranch Hand
Joined: Jan 14, 2004
Posts: 1535
|
|
This line in the Images class is probably comming up with the NullPointerException Why? In the Main class you have where each line creates a new instance of Images. Yet the Images class is designed for single-instance use. The second instantiation of Images calls createSmallImages which needs the largeImages array to have been created. But in a new instance of Images this array will be null. So try: Another (so far, unrelated) thing to look out for is this line the getScaledInstance method is asynchronous: it may return before its data is loaded.
|
 |
colin shuker
Ranch Hand
Joined: Apr 11, 2005
Posts: 712
|
|
I initially was using images.createLargeImages(), and images.createSmallImages(), But I thought I would try it without Saving an Image instance... But the 2 arrays in the Images class are static, so it shouldn't matter how many instances I use. You are absolutley correct about the null pointer exception coming from the line I forgot to mention that earlier, but pixels is coming out as null. But not null on my pc, so I'm not sure if the images on my friends computer are not being saved to the largeImages field in time for when createSmallImages is called, or if there is a problem with grabPixels() method. I guess inside the grabPixels method, I could test if the argument (Image image) is null or not. Any other ideas? Thanks
|
 |
colin shuker
Ranch Hand
Joined: Apr 11, 2005
Posts: 712
|
|
Hi again, I've found the problem, and it is what I suspected. The createSmallImages() method is being called before the createLargeImages() method completes. So in my constructor, I have: So I need the code above to be executed in order, but I'm not sure if I should start a new Thread, to do this, please can you help me work out the best way to execute the above code in that order. Thanks very much for everyones help.
|
 |
Campbell Ritchie
Sheriff
Joined: Oct 13, 2005
Posts: 32704
|
|
Try something simple first. Try synchronizing the createLargeImages and createSmallImages methods. Alternatively, try a "Thread.sleep" between the two calls. See whether those suggestions make any difference.
|
 |
Craig Wood
Ranch Hand
Joined: Jan 14, 2004
Posts: 1535
|
|
So I need the code above to be executed in order, but I'm not sure if I should start a new Thread I don't think a new Thread would help with the execution order but could be useful if the image loading/subdividing took a long time — doing it in a background thread would leave the gui responsive. May not be a problem. please can you help me work out the best way to execute the above code in that order I had trouble downloading your jar file so I made up some images and tried out your code. Your original syntax new Images().createXXX worked okay, no exceptions. The design seems to have problems in two (related) areas: possible state confusion and potential sequencing difficulties. The first problem area seems to be that since the arrays are static you have to be careful when and where you change/access them; there can be uncertainty about their state at any time. To avoid this I tried eliminating everything static and set it up it for one–time/instance use. The second problem area (which you mentioned) seems to be calling the separate methods from outside the class. To eliminate this I changed things so we could tell the class what we want and have it return the subImages, handling the scheduling on its own. I decided to leave in the helper_image_making method in case you wanted to use it for testing. If so, be careful that the hard–coded path doesn't overwrite anything.
|
 |
colin shuker
Ranch Hand
Joined: Apr 11, 2005
Posts: 712
|
|
Excellent stuff!!! I've made the same changes to my program, and it still works, I'll have to wait till tomorrow before I can test it on my friends computer. Before the only way I could get the createImage(new MemoryImageSource(...)) to work, was to extend JPanel, but using that toolkit is much better. Thanks for taking time to look at my code, I know its unappealing trying to work with a chunk of someones code, and trying to figure out what its purpose is, but I think you understand my code better than me! Thanks again, I'll let you know how I get on when I run it on friends pc.
|
 |
colin shuker
Ranch Hand
Joined: Apr 11, 2005
Posts: 712
|
|
Hi... I modified my code accordingly, but my friend Jeff is still getting an error on his pc, but now it seems that createSmallImages() isn't called at all. The code called from the constructor of Main class: Also in main class, I create a static field String X=""; Inside the createImages method, output is added to X, then X is displayed in the GUI (Note, I can't easily test this, since there is no error on my pc, and my friend doesn't have a clue about how to fix it on his pc). Here is all of the Images class: On my pc(where it works!) X comes out as... "LSL0L0L1L1L2L2L3L3L4L4L5L5LFsSs0s0s1s1s2s2s3s3s4s4s5s5sF", Which follows exactly the order of execution. On my friends pc(where it doesn't work) X comes out as... "LSL0" So it seems the exception is being thrown here: But this doesn't make sense, since if he presses a button to load in a new set of images, then this method is called, and there is no problem. I'm totally stumped with this, I don't see how it can cause an exception when called in the constructor, but work fine when a button invokes it. Any ideas? Thanks
|
 |
Craig Wood
Ranch Hand
Joined: Jan 14, 2004
Posts: 1535
|
|
if he presses a button to load in a new set of images, then this method is called, and there is no problem. I don't see anything that might be causing this and haven't been able to replicate it. Let's open things up a bit and see if we can get some indication of what's messing us up. Changes to ImagesTest:
|
 |
colin shuker
Ranch Hand
Joined: Apr 11, 2005
Posts: 712
|
|
Thanks Craig, great work! I had to modify the filepath slightly, eg if you have a set of 6 cat pics, they would be in "Cats" directory, so the filepath would be "images/Cats/pic0.jpg" and so on... Anyway, I emailed Jeff the new Jar file, and he sent me the value of X, and this is what I got... CLI:f= .DS_Store con NULLpath[0] = images/.DS_Store/pic0.jpg LDSTS=4 W=-1 H=-1 CLI ERR:java.lang.IllegalArgumentException: Width (-1) an(bit missing here) At first I thought it was a typo, but it seems he has a subfolder of images called ".DS_Store", because its there twice. He is using a Mac, and its possible to use "." in a Mac, but on my pc, I wasn't allowed to start a file using ".". As you can see, the file.list() returns NULL, so quoting the File.list() from the Java 1.4 API...
Returns null if this abstract pathname does not denote a directory, or if an I/O error occurs.
I don't think it could have been an error since more data was added to X meaning the code continued executing, so 'file' was not a directory. So hopefully thats the solution, and perhaps the other folders he named didn't start with ".", so that calling createImages(folder,W) works fine. He won't be on for 8 hours, but I'll get him to try it with a new subfolder name. Does the above make sense? Thanks
|
 |
colin shuker
Ranch Hand
Joined: Apr 11, 2005
Posts: 712
|
|
OK, you can ignore that last post, he didn't create a subfolder inside images, called .DS_Store, MAC OSX automatically generates these invisible files, so instead of reading in the folder name "Cats", it reads in the file name ".DS_Store", which of course has no pictures inside it. So I just need to write code to ignore these files. Thanks for everyones help.
|
 |
 |
|
|
subject: Tricky NullPointerException Problem
|
|
|
|