How to disable/manage garbage collection?

Please critique this post as i'm very new to posting on forums. I've been jumping between processing to openFrameworks for quite some time trying to develop a decent game engine to work with. The reason i was using openFrameworks for a while was because i kept getting strange null pointer exceptions that i just couldn't resolve. I've since moved back to processing because of how difficult it was to create nested classes in c++(especially once i started trying to link them in separate files). While processing somewhat excels with prototyping in that it doesn't require much linking, i'm facing this null pointer exception once again... and i think i found the culprit. I believe it's the garbage collector(gc) done by the JVM. I can handle raw pointers pretty well when making the game engine but relying on the gc seems to be a pain. In a past proto game i made; the game objects i used were in a hash table. I lost the copy of that game but my guess is that the gc cleaned out objects that weren't being used at the time(causing some objects to turn null). In my current version of the game engine i've not tested out any objects that were hash mapped as of yet however i noticed something which has brought me to the tons of research and eventually these humble forums.

Now that that's out of the way let me demonstrate exactly what i'm talking about. I'm using processing 2.2.1 though i doubt it would have much to do with this. Here's the classes I've setup. The problem is explained below.

Level[] l;
void setup(){
  l = new Level[1];
  for(int i = 0; i < l.length; i++){
    l[i] = new Level();
  }//a single level would work instead of an array but this for 
//when it's desirable to add more than one running level at a time
  size(500,500);
}

void draw(){
  background(0);
  for(int i = 0; i < l.length; i++){
    //l[i].run();
  }
}

void mousePressed(){
  l[1].phys.cl.loadMap();//****added just recently to show the problem****//
//if you remove the above than the problem "seems" to go away but it's just
//cause the string isn't being called on again.
}
//below is spread around different files but i doubt it would matter much
//I've gutted out a lot of the unnecessary code.

class Level{  //level contains all game objects as well as a personal physics engine
  public
  abstract class BPActor{}
  //just a bunch of level objects i was testing
  class dummy extends BPActor{}
  class player extends BPActor{}
  abstract class NPC extends BPActor{}
  Physics phys;
  Level(){  //dont let this class have same method names as it's inner classes
    phys = new Physics(this);  //this is the physics engine which has a reference to the level
  }
}

//here is the physics engine class's file
//note that the physics engine has it's own hash table and loads data to it from the "chunk loader" class.

abstract class PhysicsBlueprint{
  public
  Level rl;
  ChunkLoader cl;

  void build(){
    cl.loadMap();
  }
}



class Physics extends PhysicsBlueprint{
  public

  Physics(Level _l){
    rl = _l;
    cl = new ChunkLoader(this);
    build();
  }
}

//the last file is for a chunk loader class.  this is what takes data from files and loads it into the hash table.

class ChunkLoader{
  public
  String lines[];
  Physics phys;

  ChunkLoader(Physics _p){
    phys = _p;
  }
  void loadMap(){
    lines = loadStrings("../list.txt");//use list.txt instead of ../list.txt if you are using a data folder but the list file is outside it
    println("there are " + lines.length + " lines");
    for (int i = 0; i < lines.length; i++) {
      //println(lines[i]);  //disabled due to file being too big to log.
    }
  }
}  //OK THAT'S IT.

//the file i referenced was very large for testing purposes. Maybe the JVM didn't like that. //however i test with a small file shows the exact same results.

First save this code into a sketch and make sure to include a dummy list.txt with a few lines of dummy text into the saved folder. The txt file must have more than one line.

Now here's the problem. If you run this code for about 1 min(resource monitor helps if the file is big enough) and press any key you'll notice a crash with a null pointer exception. And this points directly to the string called "lines" in the ChunkLoader class. This tells me that the garbage collector is indeed responsible for the null pointer. Now to repeat the question. Can i disable the garbage collector in processing or at least have a full proof easy way to get around this. If this could happen to a string what's stopping the gc from wrecking my hash table and game objects? If i can get around this I'll have a decent first game developed with a friend within a month. If anyone helps me solve this problem i'll likely make all game engines/level editors i create with processing open source. Other wise i'll have to go back to c++ and openFrameworks. Apologies for the rambling and am grateful for any help/critique.

Answers

  • edited October 2015

    alright fixed post be putting the code in a code block.lol

  • Your code only gives me an ArrayIndexOutOfBoundsException , because of this line:

    l[1].phys.cl.loadMap();

    Changing the index to 0 fixes this error, but i still can not reproduce your problem and never had any problems with garbage-collection freeing ressources that are still used.

  • edited October 2015
    • Indeed for l = new Level[1];, maximum (and only valid) accessible index for l is [0] (:|
    • Nonetheless, we usually don't keep loadStrings()'s original content in some permanent field.
    • Rather we split() those lines, parse and transfer each substring unit to their respective fields.
    • Also we should avoid loading resources after setup().
    • Unless they're too big/many or they're dynamically changed on-the-fly.
    • Although code is formatted, it still feels very crammed up in many places.
    • It lacks spaces between words & braces. And lacks empty lines between code sections.
    • In short, that ArrayIndexOutOfBoundsException got nothing to do w/ the GC getting rid of an object before its "time": :-@

    http://forum.Processing.org/two/discussion/8070/why-do-i-get-an-arrayindexoutofboundsexception

  • first i'd like to thank both of you for your input. let me apologize for the strange way the code was laid out. i have very bad eyesight so when i make the font bigger i need the text close to each other to fit as much on screen as i can. however since you pointed this out as being a burden for reading i'll be sure to fix this in the future. so again thanks for the input. also i noticed that the error you pointed out is indeed where the problem was not the string itself. i should have taken my time instead of jumping to conclusions from exhaustion. the reason i believed there would be a problem was cause when i tested this with a large file and didn't use the keyPressed function i noticed that processing was at first taking over 1gb ram for holding the string. but once i waited a min it dropped down to half that. i was under the impression that the string went missing or got collected. however by fixing the l[1].phys.cl.loadMap(); to l[0].phys.cl.loadString(); and adding this function to ChunkLoader class.

        void loadString(){
        println("there are " + lines.length + " lines");
            for (int i = 0; i < lines.length; i++) {
              //println(lines[i]);  //disabled due to file being too big to log.
            }
        }
    

    i've now noticed that indeed the string does load properly and is not garbage collected. still how can a 1gb string in ram jump down to half that after a min? is the sketch just storing the bulk of the string in the hard drive until it's called again? if anyone has info on how either large data is stored or how strings are stored with time i'd appreciate it. also just to point out yes i am wanting to load the string dynamically. the reason is because i'm making this for android and from what i read smart phones often has no more than 4gb ram at best. so i thought storing something close to an oct tree in the hard drive but loading the data as the player moves form one chunk to another would be the best approach. this way the game world can be very open and wont have to deal with any loading screens. i appreciate the help and patience i've gotten so far and am grateful for any further input.

  • edited October 2015 Answer ✓

    ... as being a burden for reading, I'll be sure to fix this in the future.

    In the PDE (Processing's IDE), we can hit CTRL+T in order to auto-indent & format our code. :bz

    Still how can 1GB String in RAM jump down to half that after a min.?

    Java's (and JS') garbage collector doesn't immediately get rid of discarded objects.
    1st it needs to make a "list" of which 1s are indeed eligible to be garbage-collected.
    When it decides it's a "good time" to do it, then that "list" is finally taken care of. :-\"

    Moreover, we should be aware loadStrings(), and other functions as well, can create many temporary objects in order to do their job.
    That is, they generate their own extra garbage which will linger on for some time till GC kicks in! ~O)
    That's probably why you see 1GB drop to half of it after some time had passed after loadStrings().

    Yes, I am wanting to loadStrings() dynamically.

    Then you should consider using thread("") in order to avoid load & save slowdowns:
    https://Processing.org/reference/thread_.html

    Also consider replacing loadStrings() & saveStrings() w/ loadTable() & saveTable() respectively:
    https://Processing.org/reference/loadTable_.html
    https://Processing.org/reference/saveTable_.html

  • wow this is exactly what i'm looking for. thanks a lot you've saved me not one but several headaches. if the garbage collector really isn't as bad as i thought it was than perhaps now all that's left is to finish the game engine and continue adding on to it. i can't thank you enough for the help. first personally made opensource level editor/game engine here i come:) if i can use this to help other folks than i'll have lived a full life:)

Sign In or Register to comment.