Need help with StackOverflowError

Hi all, first post here, I need some help with a high school Java project which is throwing a stack overflow exception everytime I click a button which runs a method. It's basically a database program for storing information of computer game characters. It's a very simple problem compared to the complexity of a lot of the other problems I have read about here - it grabs info I have in a form on a GUI, then tries to add it to a binary tree then save it to a file.

I'm tearing my hair out with this project, I'd be really appreciative of anybody who would be willing to help me out, if so please drop me an email at g0t-h4x@optusnet.com.au or just leave your email here. I want to be able to talk through the problem and understand why it won't work, because I've done some reasearch and judging by example codes I've been given, there's nothing wrong. I hope this doesn't sound like I'm begging or whining or pleading for someone to make my whole project, but I just want to be able to go through the Overflow error and understand why it's happening.

Thanks.

Message was edited by:

NochnoiDozor

[1140 byte] By [NochnoiDozora] at [2007-10-3 4:06:33]
# 1

Obviously the most likely cause of a stack overflow error is an endless loop.

The simplest way to trace down the loop that is causing the problem is to put a System.out.println() in every method that could conceivably be called, and then run the progam and see what is being called over and over again.

Alternatively if you are using an IDE you can use the debugger to single-step through the code.

TimRyanNZa at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 2
I am using the Eclipse IDE, but the problem is, I get a "source not found" error while debugging the methods in question that I think are causing the stack overflow.I have no idea why this error comes up, but it makes debugging the methods impossible.
NochnoiDozora at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 3
Is the "source not found" in your code or Sun classes?
TimRyanNZa at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 4

It's a part of Eclipse, the error isn't a part of anything that I've coded myself.

It seems I've progressed a bit now... instead of overflowing the stack the program just shuts down when the methods which were overflowing the stack are executed. Getting a bit closer I hope!

Message was edited by:

NochnoiDozor

NochnoiDozora at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 5
Sorry, what I meant was - which class can it not find the source for, not who is producing the error message?
TimRyanNZa at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 6

Well, it produced the error *I think* when it tried to interact with my .dat file. So I believe it came up with the error when debugging and a method which accessed my File class (which had all methods related to my file ie. read/write).

Sorry I can't give you more info, but now the program is crashing whenever it makes any one of these calls. Arg!

EDIT: OK so I manged to replicate the error again... it happened in this case when I created a new object for one of my GUI classes.

It's a Class File Editor Source not found error.

The souirce attachment does not contain the source for the file ClassLoader.class (which isn't one of the classes I made)

Then it lists heaps of seemingly random variable, array and class declarations.

Would it be easier if I just posted all of my code instead? That would probably be easier than trying to figure out why Eclipse won't debug.

NochnoiDozora at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 7

> which accessed my File class

Don't create a class called File - that's an important Sun class and it is very rarely appropriate to give your own class the same name as a Sun class - rename your class to some other name.

> Would it be easier if I just posted all of my code

> instead? That would probably be easier than trying to

> figure out why Eclipse won't debug.

Probably.

In any case if the problem is in the ClassLoader, then maybe you have a class that is recursively constructing itself - have a look in your constructors for calls to new.

TimRyanNZa at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 8

OK, I'll rename the File class to something else, see if that makes a difference.

Edit: No, that didn't make any difference. Here are the moethods I have which use recursion which might be causing the problem:

addHero class, just enters all my data (Hero objects) into a binary tree

public void addHero(Hero root, Hero newHero){

if(root == null){//check for empty tree

root = newHero;

}

else{

Hero current = root;

if(newHero.getName().compareToIgnoreCase(current.getName()) < 0){

if(current.getLeft() == null){//end of branch

current.setLeft(newHero);//attach node to tree

}

else{//there are more nodes in the branch

current = current.getLeft();//grab next node to left of current node (in this case root)

addHero(current, newHero);//recursive call to repeat process checking for free space

}

}

else{//new node must be greater than current node

if(current.getRight() == null){//don't need to check if name is greater than or equal to zero because if it isn't less than as tested before it must be greater than

current.setRight(newHero);

}

else{

current = current.getRight();

addHero(current, newHero);//recursive call

}

}

}

viewDatabase(root);

LoadSave temp = new LoadSave(root);

temp.inputHero(newHero);

}

and retrieveDatabase which gets all my Hero data from a dat file, but for some reason it doesn't seems to be recognising it.

public Hero[] retrieveDatabase(){

Hero root = new Hero();

LoadSave temp = new LoadSave(root);

Hero[] tempArray = new Hero[temp.countRecords()];

for (int x = 0; x < temp.countRecords(); x++){

//Hero outputHero = new Hero();

String name = temp.readName(x);

String heroClass = temp.readHeroClass(x);

String primaryAttribute = temp.readPrimaryAttribute(x);

String heroType = temp.readHeroType(x);

String affiliation = temp.readAffiliation(x);

int armour = temp.readArmour(x);

int strength = temp.readStrength(x);

int agility = temp.readAgility(x);

int intelligence = temp.readIntelligence(x);

double strengthGainPerLevel = temp.readStrengthGainPerLevel(x);

double agilityGainPerLevel = temp.readAgilityGainPerLevel(x);

double intelligenceGainPerLevel = temp.readIntelligenceGainPerLevel(x);

int damage = temp.readDamage(x);

int attackRange = temp.readAttackRange(x);

String skill1 = temp.readSkill1(x);

String skill2 = temp.readSkill2(x);

String skill3 = temp.readSkill3(x);

String ultimateSkill = temp.readUltimateSkill(x);

String description = temp.readDescription(x);

Hero toBeLoaded = new Hero();

toBeLoaded.setName(name);

toBeLoaded.setHeroClass(heroClass);

toBeLoaded.setPrimaryAttribute(primaryAttribute);

toBeLoaded.setType(heroType);

toBeLoaded.setAffiliation(affiliation);

toBeLoaded.setArmour(armour);

toBeLoaded.setStrength(strength);

toBeLoaded.setAgility(agility);

toBeLoaded.setIntelligence(intelligence);

toBeLoaded.setStrengthGainPerLevel(strengthGainPerLevel);

toBeLoaded.setAgilityGainPerLevel(agilityGainPerLevel);

toBeLoaded.setIntelligenceGainPerLevel(intelligenceGainPerLevel);

toBeLoaded.setDamage(damage);

toBeLoaded.setAttackRange(attackRange);

toBeLoaded.setSkill1(skill1);

toBeLoaded.setSkill2(skill2);

toBeLoaded.setSkill3(skill3);

toBeLoaded.setUltimateSkill(ultimateSkill);

toBeLoaded.setDescription(description);

tempArray[x] = toBeLoaded;

}

return tempArray;

}

Message was edited by:

NochnoiDozor

NochnoiDozora at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 9
> Edit: No, that didn't make any difference. I didn't expect it to - just trying to help you learn better techniques. :-)
TimRyanNZa at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 10
Thanks, I had no idea File was an in-built Java class.
NochnoiDozora at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 11

Ahh I think I see your problem.

You have this codeviewDatabase(root);

LoadSave temp = new LoadSave(root);

temp.inputHero(newHero);

inside your recursive addHero() routine - that definitely doesn't seem right to me.

I'm off to bed now - hopefully you can sort it out or someone else can help.

TimRyanNZa at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 12
But that's outside any of the loops, therefore it will only execute once after all the recursive calls have been completed (the object has been added to the right place), won't it? Where else could I put that section of code?
NochnoiDozora at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 13

StackOverflowError is common in recursion gone wrong. It means that your recursive method does not have a proper stopping condition, so your code calls it, and calls it, and calls it....you get the idea.

Check your recursive method and make sure the stopping condition is correct.

Another suggestion: why are you not taking the time to write a separate BinaryTree class that can hold any kind of data? That might be generally useful, even outside your academic Hero database assignment.

%

duffymoa at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 14
Well my main class functions more or less as a binary tree class. It has all the adding/removing methods and such.And another question: if the program is now crashing instead of overflowing the stack, is it likely the cause of the problem is the same?
NochnoiDozora at 2007-7-14 22:06:02 > top of Java-index,Java Essentials,New To Java...
# 15

> Well my main class functions more or less as a binary

> tree class. It has all the adding/removing methods

> and such.

You'd be better served if the binary tree code was generalized and moved outside your main class. You'd have something useful outside the context of your current app. It'd be like a java.util.Map.

> And another question: if the program is now crashing

> instead of overflowing the stack, is it likely the

> cause of the problem is the same?

Can't tell, since I don't know what "crashing" looks like. What messages do you get? And did you re-examine your recursive method to see if your stopping condition was correct? If not, you probably made the wrong change.

%

duffymoa at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 16

> But that's outside any of the loops, therefore it

> will only execute once after all the recursive calls

> have been completed (the object has been added to the

> right place), won't it?

Sorry, no you're wrong - it will be called at the end of each recursion (remember the calls all have to return and each parent then continues to run to its end).

> Where else could I put that

> section of code?

You need to put it in the external caller of the recursive method.

TimRyanNZa at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 17

OK I moved that section of code to the appropriate place, seems to be working better there.

EDIT: Sorry, I'm a complete idiot - I was looking for a file to be created in a folder which wasn't actually my workspace. It's actually creating the file fine when I thought it wasn't. D'oh!!!

Message was edited by:

NochnoiDozor

NochnoiDozora at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 18
I have another question now: is there a String method that can receive a String and then, if the String is, say, 20 characters long, insert 80 spaces behind the first 20 characters to create a 100-characters long String? If there isn't such a method, what's the easiest way to do this?
NochnoiDozora at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 19

> is there a String method that can...

The String methods are described here ;)

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html

> receive a String and then, if the String is, say, 20 characters long, insert 80

> spaces behind the first 20 characters to create a 100-characters long

> String

If you're using 1.5 the following may be useful:public static void main(String[] args) {

String str = "foo";

String paddedStr = String.format("%100s", str);

System.out.println("|" + paddedStr + "|");

paddedStr = String.format("%-100s", str);

System.out.println("|" + paddedStr + "|");

}

This pads with just enough spaces to make the string length 100.

pbrockway2a at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 20
Hmm, it doesn't seem to work for me - it tells me that the method format(String, String) is undefined for type StringFrom the JAva classes list I saw that the format method needed a String and an Object argument, maybe that's the problem?
NochnoiDozora at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 21

A String is an Object, so that's not a problem.

The String.format() method only became available with java 1.5 so if you're

getting a message saying it is undefined then your compiler is either not 1.5 or

has been told not to compile 1.5 code. If you're using an IDE check its settings.

At the command linejavac -versionworks for me, and reports the version as 1.5.0_06

pbrockway2a at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 22
Sorry, I can't find that line in my IDE (Eclipse 3.1.2) settings. Are there any other ways to do it?
NochnoiDozora at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 23

Also, I have deduced that this method is the one causing the Stakc overflow errors:

public Hero[] retrieveDatabase(){

Hero root = new Hero();

LoadSave temp = new LoadSave(root);

Hero[] tempArray = new Hero[temp.countRecords()];

for (int x = 0; x < temp.countRecords(); x++){

String name = temp.readName(x);

String heroClass = temp.readHeroClass(x);

String primaryAttribute = temp.readPrimaryAttribute(x);

String heroType = temp.readHeroType(x);

String affiliation = temp.readAffiliation(x);

int armour = temp.readArmour(x);

int strength = temp.readStrength(x);

int agility = temp.readAgility(x);

int intelligence = temp.readIntelligence(x);

double strengthGainPerLevel = temp.readStrengthGainPerLevel(x);

double agilityGainPerLevel = temp.readAgilityGainPerLevel(x);

double intelligenceGainPerLevel = temp.readIntelligenceGainPerLevel(x);

int damage = temp.readDamage(x);

int attackRange = temp.readAttackRange(x);

String skill1 = temp.readSkill1(x);

String skill2 = temp.readSkill2(x);

String skill3 = temp.readSkill3(x);

String ultimateSkill = temp.readUltimateSkill(x);

String description = temp.readDescription(x);

Hero toBeLoaded = new Hero();

toBeLoaded.setName(name);

toBeLoaded.setHeroClass(heroClass);

toBeLoaded.setPrimaryAttribute(primaryAttribute);

toBeLoaded.setType(heroType);

toBeLoaded.setAffiliation(affiliation);

toBeLoaded.setArmour(armour);

toBeLoaded.setStrength(strength);

toBeLoaded.setAgility(agility);

toBeLoaded.setIntelligence(intelligence);

toBeLoaded.setStrengthGainPerLevel(strengthGainPerLevel);

toBeLoaded.setAgilityGainPerLevel(agilityGainPerLevel);

toBeLoaded.setIntelligenceGainPerLevel(intelligenceGainPerLevel);

toBeLoaded.setDamage(damage);

toBeLoaded.setAttackRange(attackRange);

toBeLoaded.setSkill1(skill1);

toBeLoaded.setSkill2(skill2);

toBeLoaded.setSkill3(skill3);

toBeLoaded.setUltimateSkill(ultimateSkill);

toBeLoaded.setDescription(description);

tempArray[x] = toBeLoaded;

}

return tempArray;

}

Is it because the for loop isn't terminating? Is the loop not terminating correctly?

NochnoiDozora at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 24

> Sorry, I can't find that line in my IDE (Eclipse 3.1.2) settings.

The default settings for a project can be found from the "Window" menu item.

Preferences->Java->Compiler. You change the "Compiler compliance level"

to 5.0 and all is good.

(Strictly speaking this affects the default settings, projects can override these.

It's unlikely to be needed in your case but you get at the project specific settings by right

clicking on the project's icon then select "Properties". There is a "Java compiler"

section that also accepts the 5.0 setting. It's great the way these IDEs take

away the need to bother with such details ;)

> Are there any other ways to do it?

The pre-1.5 way would be like the followingpublic static void main(String[] args) {

String str = "foo";

StringBuffer buf = new StringBuffer(str);

for(int i = str.length(); i < 100; i++) {

buf.append(" ");

}

String paddedStr = buf.toString();

System.out.println("|" + paddedStr + "|");

// add putting the padding on the other end

buf = new StringBuffer();

for(int i = str.length(); i < 100; i++) {

buf.append(" ");

}

buf.append(str);

paddedStr = buf.toString();

System.out.println("|" + paddedStr + "|");

}

pbrockway2a at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 25
Ah, ok that works now. However, it adds the String to the very end of the padding, so there are 80 spaces and then the 20 character long String. Is there any way to have the padding AFTER the String instead of before it?
NochnoiDozora at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 26
> Is there any way to have the padding AFTER the String instead of before it?Both the String.format() and StringBuffer.append() examples I posted illustrate two forms of padding - with the spaces at either end.
pbrockway2a at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 27

OK thanks, I think I fixed it.

What I want to know now is, why is it when my .dat file is read and the results put up on a GUI, they aren't coherent? Say, for example, the hero's name to be put onto the screen in the file is John, but instead it comes up as Hero@93d6bc.

Why's that?

NochnoiDozora at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...
# 28

> Say, for example, the hero's name to be put onto the screen in the file is John,

> but instead it comes up as Hero@93d6bc.

I haven't seen your Hero class, or how it's being put onto the screen, so this is

guesswork...

Strings like "Hero@93d6bc" are typical of what Java produces when you ask it

for the string form of an object. To get a more meaningful string you have to

provide the Hero class with a toString() method. Like this:// somewhere in the Hero class

// maybe in a constructor or a setter or whereever

String name = "John";

public String toString() {

return name;

}

The toString() method can return any string you like, and can

construct that string any way you like.

(It would probably be a good idea if you posted different questions in

different threads - it would save confusion. For instance if the stack overflow

problem still exists it will become lost in the noise.)

pbrockway2a at 2007-7-21 10:24:02 > top of Java-index,Java Essentials,New To Java...