Solved

java program getting out of memory error

Posted on 2010-11-10
22
429 Views
Last Modified: 2013-11-23
It is getting an out of memory error.  Feel it is something with the borrowed ArrayQueue class at the end of the code.  No matter what I try, can't get around the damn error message.  I get the feeling that I am getting rightward creep in the array.  Should there be a shift in the array somewhere?

please help!!!!  I am at a deadline.


import java.util.Scanner;

public class bank {

 //  initalize global variables
 static ArrayQueue waitingCustomers= null;
 static ArrayQueue finishedCustomers=null;
 static Customer tellerWindow[] = new Customer[6];
 static Teller tellerArray[]= new Teller[6];
 static int tstTotCusts = 0;
 static int tstTotServed = 0;
 static int tstCustomersInQueue= 0;
 static int tstCustomersinFinishedQueue=0;
 static long nextCustomerTime;
 static Customer newCustomer = null;
 static Customer finishedCustomer = null;
 static Customer waitCustomer = null;
 static Teller Teller1 = null;
 static Teller Teller2 = null;
 static Teller Teller3 = null;
 static Teller Teller4 = null;
 static Teller Teller5 = null;
 static long startTime = 0;
static boolean waitCustQueueEmpty = false;
static boolean finiCustQueueEmpty = true;

 public static void main(String[] args) {

//    String inAnsYN = "N";  // Declare & initialize a String to hold input.
    Scanner inAns = new Scanner(System.in); // Decl. & init. a Scanner.

    while (true){

    boolean loopEnd = false;
    workLoop();
    endPrintout();
    while (!loopEnd){
    System.out.println("Do you want to run the program again? (Y/N) ");
    char cInAns=inAns.next().charAt(0);

    if (cInAns=='Y' || cInAns=='y') loopEnd=true;
    else if (cInAns=='N' || cInAns=='n') return;
    }
    }
  }
// ============================================================================
  private static void workLoop(){
    initVars();
    boolean firstTime=true;
    int custLoopCT = 0;

     //  go ahead and set loop start time
    startTime =  System.currentTimeMillis();
    //  go ahead and populate queue with 5 customers per jbhola
    waitingCustomers = new ArrayQueue();
    finishedCustomers = new ArrayQueue();
    for (int i = 0; i < 5; i++) createCust();

    nextCustomerTime=startTime+getRandomNum(2,6)*100;
    //  go ahead and assign first teller randonmly per jbhola
    assignTeller(getRandomNum(2,5));
   long tstTime = System.currentTimeMillis();

    // =========>  MAIN LOOP  <========
    while (System.currentTimeMillis() < startTime+12000){
//      long loopBeginTime= System.currentTimeMillis();
      bankLoop();
  tstTime = System.currentTimeMillis();

    }

     long endTime =  System.currentTimeMillis();

  }
// ===========================================================================
  private static void bankLoop(){
    long loopStartTime=System.currentTimeMillis();
    if (loopStartTime>nextCustomerTime){
        createCust();
    }
    // teller loop
    for (int j = 1;j<6;j++){
      if (tellerArray[j].available || tellerWindow[j].empty){
          assignTeller(j);
      }
      else  if (tellerWindow[j].endTime < loopStartTime){
          clearTeller(j);
      }
    }
     
  }
 
// ===========================================================================
  private static void createCust(){
    Customer outCust = new Customer(getRandomNum(2,5));

    outCust.intervalTime=getRandomNum(2,5)*1000;
    //  push onto newCustomerQueue
    try {
        waitingCustomers.enqueue(outCust);
        tstCustomersInQueue++;
    } catch (NullPointerException e){
        System.out.println("Error adding to queue");
    } catch (OutOfMemoryError e){
        System.out.println("Out of memory enqueuing customer");
    }
  }
// ===========================================================================
  private static Customer getNextCust(){
    Customer outCust = waitingCustomers.dequeue();
    if  (waitCustQueueEmpty) {;
         outCust = new Customer();
         return outCust;
        }
    nextCustomerTime=startTime+getRandomNum(2,6)*100;
    tstCustomersInQueue--;
    return outCust;
  }
  // ===========================================================================
  private static void initVars(){

 waitingCustomers= null;
 finishedCustomers=null;
 tstTotCusts = 0;
 tstTotServed = 0;
 tstCustomersInQueue= 0;
 tstCustomersinFinishedQueue=0;
nextCustomerTime=0;
newCustomer = null;
 finishedCustomer = null;
waitCustomer = null;
initTellers();
 startTime = 0;  }
  // ===========================================================================
  private static void initTellers(){
for (int t = 0;t<6;t++){
    tellerWindow[t]= new Customer();
    tellerArray[t]=new Teller();
}
  }
// ==========================================================================
  private static void assignTeller(int tellerNum){
     // need way to tell if customer already in teller array cell
     tellerWindow[tellerNum]=getNextCust();
  /// need some check  to make sure there was a customer in queue
     tellerWindow[tellerNum].setTeller(tellerNum);
     // setting start time also sets endtime
     tellerWindow[tellerNum].setStartTime(System.currentTimeMillis());
     tellerArray[tellerNum].totalPeople++;
     tellerArray[tellerNum].available=false;
     tstTotCusts++;
      }
 
// ==========================================================================
  private static void clearTeller(int tellerNum){
     // calculate actual time, not just interval time
      long elapsedTime = System.currentTimeMillis() -
              tellerWindow[tellerNum].startTime;
                                            // get Customer address from array
      Customer finishedCust=tellerWindow[tellerNum];
      finishedCust.assignedPerson=0;            //  clear assigned person
//      finishedCustomers.enqueue(finishedCust);  // put in finished queue
      tstCustomersinFinishedQueue++;            // update total
//      tellerWindow[tellerNum]=null;              // clear array cell
      //  update total time for teller and set available flag
      tellerArray[tellerNum].timeOccupied+=elapsedTime;
      tellerArray[tellerNum].available=true;
      tellerWindow[tellerNum]= new Customer();  // assign empty customer object
      tstTotServed++;
  }
// =========================================================================
  private static int getRandomNum(int Min, int Max) {
    int intReturn = Min + (int)(Math.random() * ((Max - Min) + 1));
    return intReturn;
  }
// =========================================================================
 public static void endPrintout(){
    System.out.println("Total amount of customers that visited the bank is "+
           tstTotCusts );
    System.out.println("Total amount of customers for teller 1 is "+
           tellerArray[1].totalPeople);
    System.out.println("Total amount of time teller 1 was occupied is "+
         ((tellerArray[1].timeOccupied) / 1000) % 60);
    System.out.println("Total amount of customers for teller 2 is "+
           tellerArray[2].totalPeople);
    System.out.println("Total amount of time teller 2 was occupied is "+
         ((tellerArray[2].timeOccupied) / 1000) % 60);
    System.out.println("Total amount of customers for teller 3 is "+
           tellerArray[3].totalPeople);
    System.out.println("Total amount of time teller 3 was occupied is "+
         ((tellerArray[3].timeOccupied) / 1000) % 60);
    System.out.println("Total amount of customers for teller 4 is "+
           tellerArray[4].totalPeople);
    System.out.println("Total amount of time teller 4 was occupied is "+
         ((tellerArray[4].timeOccupied) / 1000) % 60);
    System.out.println("Total amount of customers for teller 5 is "+
           tellerArray[5].totalPeople);
    System.out.println("Total amount of time teller 5 was occupied is "+
         ((tellerArray[5].timeOccupied) / 1000) % 60);
    System.out.println("Total amount of customers left in queue is "+
            tstCustomersInQueue );
 }
// =========================================================================
public static class Teller  {

    private Boolean available;
    private int assignedPerson;
    private int totalPeople;
    private long timeOccupied;
    private int intervalTime;         // 1 second = 1000 millis()
    private long startTime;
    private long endTime;

// constructor
    public Teller() {
      available = true;
      intervalTime = 0;
      assignedPerson = 0;
      totalPeople = 0;
      timeOccupied=0;
      startTime = 0;
      endTime = 0;
    }

   // methods - obvious what they do so do not need individual comments
    public long getEndTime() {
      return endTime;
    }
 }

public static class Customer  {
    private Boolean available;
    private int assignedPerson;
    private int totalPeople;
    private long timeOccupied;
    private int intervalTime;         // 1 second = 1000 millis()
    private long startTime;
    private long endTime;
    private boolean empty;
// constructor
    //  create empty customer to fill tellerWindow if necessary
    public Customer() {
      available = true;
      intervalTime = 0;
      assignedPerson = 0;
      totalPeople = 0;
      timeOccupied=0;
      startTime = 0;
      endTime = 0;
      empty=true;
    }
    public Customer(int inTime) {
      available = true;
      intervalTime = inTime;
      assignedPerson = 0;
      totalPeople = 0;
      timeOccupied=0;
      startTime = 0;
      endTime = 0;
      empty=false;
    }

   // methods - obvious what they do so do not need individual comments
    public void setTeller(int i) {
       assignedPerson=i;
       available=false;
    }
    public void clearTeller(){
        assignedPerson=0;
        available=true;
    }
    public void setStartTime(long inTime){
        startTime=inTime;
        endTime=startTime+intervalTime;
    }
    public long getEndTime() {
      return endTime;
    }
 }
//  +++++++++++++++++++++++++++  borrowed code
// ArrayQueue class
//
// CONSTRUCTION: with no initializer
//
// ******************PUBLIC OPERATIONS*********************
// void enqueue( x )      --> Insert x
// Object getFront( )     --> Return least recently inserted item
// Object dequeue( )      --> Return and remove least recent item
// boolean isEmpty( )     --> Return true if empty; else false
// void makeEmpty( )      --> Remove all items
// ******************ERRORS********************************
// getFront or dequeue on empty queue

/**
 * Array-based implementation of the queue.
 */
public static class ArrayQueue implements Queue
{
    /**
     * Construct the queue.
     */
    public ArrayQueue( )
    {
        theArray = new Customer[ DEFAULT_CAPACITY ];
        makeEmpty( );
    }

    /**
     * Test if the queue is logically empty.
     * @return true if empty, false otherwise.
     */
    public boolean isEmpty( )
    {
        return currentSize == 0;
    }

    /**
     * Make the queue logically empty.
     */
    public void makeEmpty( )
    {
        currentSize = 0;
        front = 0;
        back = -1;
    }

    /**
     * Return and remove the least recently inserted item
     * from the queue.
     * @return the least recently inserted item in the queue.
     * @throws UnderflowException if the queue is empty.
     */
    public Customer dequeue( )
    {
        if( isEmpty( ) ) {
         waitCustQueueEmpty=true;
         Customer returnValue = new Customer();
         return returnValue;
        }
            //            new UnderflowException( "ArrayQueue dequeue" );
        currentSize--;

        Customer returnValue = theArray[ front ];
        front = increment( front );
        return returnValue;
    }

    /**
     * Get the least recently inserted item in the queue.
     * Does not alter the queue.
     * @return the least recently inserted item in the queue.
     * @throws UnderflowException if the queue is empty.
     */
    public Customer getFront( )
    {
        if( isEmpty( ) ) {
         waitCustQueueEmpty=true;
         Customer returnValue = new Customer();
         return returnValue;
        }
 //           throw new UnderflowException( "ArrayQueue getFront" );
        return theArray[ front ];
    }

    /**
     * Insert a new item into the queue.
     * @param x the item to insert.
     */
    public void enqueue( Customer x )
    {
        if( currentSize == theArray.length )
            doubleQueue( );
        back = increment( back );
        theArray[ back ] = x;
        currentSize++;
    }

    /**
     * Internal method to increment with wraparound.
     * @param x any index in theArray's range.
     * @return x+1, or 0 if x is at the end of theArray.
     */
    private int increment( int x )
    {
        if( ++x == theArray.length )
            x = 0;
        return x;
    }

    /**
     * Internal method to expand theArray.
     */
    private void doubleQueue( )
    {
        Customer [ ] newArray;

        newArray = new Customer[ theArray.length * 2 ];

            // Copy elements that are logically in the queue
        for( int i = 0; i < currentSize; i++, front = increment( front ) )
            newArray[ i ] = theArray[ front ];

        theArray = newArray;
        front = 0;
        back = currentSize - 1;
    }

    private Customer [ ] theArray;
    private int        currentSize;
    private int        front;
    private int        back;

    private static final int DEFAULT_CAPACITY = 12;


}

/**
 * Exception class for access in empty containers
 * such as stacks, queues, and priority queues.
 */
public static class UnderflowException extends RuntimeException
{
    /**
     * Construct this exception object.
     * @param message the error message.
     */
    public UnderflowException( String message )
    {
        super( message );
    }
}

// Queue interface
//
// ******************PUBLIC OPERATIONS*********************
// void enqueue( x )      --> Insert x
// Object getFront( )     --> Return least recently inserted item
// Object dequeue( )      --> Return and remove least recent item
// boolean isEmpty( )     --> Return true if empty; else false
// void makeEmpty( )      --> Remove all items
// ******************ERRORS********************************
// getFront or dequeue on empty queue

/**
 * Protocol for queues.
 */
public interface Queue
{
    /**
     * Insert a new item into the queue.
     * @param x the item to insert.
     */
    void  enqueue( Customer x );

    /**
     * Get the least recently inserted item in the queue.
     * Does not alter the queue.
     * @return the least recently inserted item in the queue.
     * @exception UnderflowException if the queue is empty.
     */
    Customer getFront( );

    /**
     * Return and remove the least recently inserted item
     * from the queue.
     * @return the least recently inserted item in the queue.
     * @exception UnderflowException if the queue is empty.
     */
    Customer dequeue( );

    /**
     * Test if the queue is logically empty.
     * @return true if empty, false otherwise.
     */
    boolean isEmpty( );

    /**
     * Make the queue logically empty.
     */
    void makeEmpty( );
}

}
0
Comment
Question by:jjackson2004
22 Comments
 
LVL 10

Accepted Solution

by:
Pramod Kumar earned 125 total points
ID: 34109268
This can have two reasons:

* Your Java application has a memory leak.
* Your Java application really needs a lot of memory (more than 128 MB by default!). In this case the Java heap size can be increased using the following runtime parameters:

java -Xms<initial heap size> -Xmx<maximum heap size>

Defaults are:

java -Xms32m -Xmx128m

You can set this either in the Java Control Panel or on the command line, depending on the environment you run your application.

You may run on command prompt as: java -Xms512m -Xmx1024m bank
0
 

Author Comment

by:jjackson2004
ID: 34109432
Question is where is the leak?
0
 
LVL 8

Expert Comment

by:robthewolf
ID: 34109642
I can't quite see it but I see lots of possibilities.  Main causes of a memory leak are:
- a dynamic collection like an HashMap or an ArrayList (which usually underly queues). If you keep adding to them and never removing from them they will grow and grow until you run out of memory.
- creating objects that never get destroyed.  If you create a new object and your code holds a reference to it then it will continue to take up memory.  you may not be destroying all the new Customers that you are creating.
0
 
LVL 20

Expert Comment

by:a_b
ID: 34110297
What is the stack trace? Can you post that?
0
 
LVL 20

Assisted Solution

by:a_b
a_b earned 375 total points
ID: 34110340
The leak is here -

  while (System.currentTimeMillis() < startTime+12000){
//      long loopBeginTime= System.currentTimeMillis();
          System.out.println("test");
      bankLoop();
  tstTime = System.currentTimeMillis();

    }

The while loopk keeps running and never terminates
0
 
LVL 20

Expert Comment

by:a_b
ID: 34110346
The number of objects that you are creating in 12000ms is way more that the heap space. Hence the error. Try reducing the time.
0
 

Author Comment

by:jjackson2004
ID: 34110784
the program is supposed to run for 2 minutes, that is why I have the starttime+120000,  120000 ms is supoosed to be 2 minutes.
0
 

Author Comment

by:jjackson2004
ID: 34110787
how do you do a stack trace?
0
 

Author Comment

by:jjackson2004
ID: 34110822
A new customer object is only supposed to be created every 2-6 seconds depending on the random number generating, yet I am getting 10million+ objects.
0
 
LVL 20

Expert Comment

by:a_b
ID: 34110856
This condition will always hold true -

 long loopStartTime=System.currentTimeMillis();
    if (loopStartTime>nextCustomerTime){
        createCust();
    }

Therefore your customers are created continuously.
0
 
LVL 20

Expert Comment

by:a_b
ID: 34110871
Another side note-

public static long currentTimeMillis()
Returns the current time in milliseconds. Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 20

Expert Comment

by:a_b
ID: 34110880
Try -

int ctr = 0;
    while (System.currentTimeMillis() < startTime+12000){
//      long loopBeginTime= System.currentTimeMillis();
//          System.out.println(ctr++);
        nextCustomerTime=startTime+getRandomNum(2,6)*1000000; -> The multiplication factor might differ
      bankLoop();
      tstTime = System.currentTimeMillis();

    }
0
 
LVL 20

Expert Comment

by:a_b
ID: 34110900
Change - 1000000 to 1000. Atleast you will not run into the heap space error.
0
 
LVL 20

Expert Comment

by:a_b
ID: 34110934
Try -
while (System.currentTimeMillis() < startTime+12000){
//      long loopBeginTime= System.currentTimeMillis();
//          System.out.println(ctr++);
          try
          {
                Thread.sleep(getRandomNum(2,6)*1000);
          }
          catch(Exception e)
          {
                
          }
//        nextCustomerTime=tstTime+getRandomNum(2,6)*1000;
      bankLoop();
      tstTime = System.currentTimeMillis();

    }


and

  private static void bankLoop(){
    long loopStartTime=System.currentTimeMillis();
//    if (loopStartTime>nextCustomerTime){
       
          createCust();
//    }
0
 

Author Comment

by:jjackson2004
ID: 34115971
The problem with this last code you sent is that it ignores the teller activity that is supposed to be taking place while the new customer delay is going on.

Maybe you could show me how I could make the tellers async threads, or how I might use the timer class to create autonomous tellers.

Thanks in advance
0
 

Author Comment

by:jjackson2004
ID: 34116009
As to the loop always being true

    nextCustomerTime=startTime+(getRandomNum(2,6)*1000);

this code is supposed to be adding 2-6 seconds to the loopstart time.  I assumed the loop would be occurring in the milliseconds range and would not take 2-6 seconds to get through.
0
 
LVL 20

Expert Comment

by:a_b
ID: 34117706
Can you explain to me what the program is doing? I would be able to better advise you then.
0
 

Author Comment

by:jjackson2004
ID: 34117931
from an earlier thread:

my scenario is that the life of this program is a 2 minute period.  Basically, it is a bank scenario. for 2 minutes,  I generate a customer at a random 2-6 sec interval and queue them up.  Have 5 tellers which I will just use class objects for.  A customer will be with each teller for 2-5 secs (random generated).  Time up and a new customer is taken from the queue and put with that teller.  At end of two mins I will flush the queue and print results.  
0
 
LVL 20

Assisted Solution

by:a_b
a_b earned 375 total points
ID: 34118066
You will have to use Threads for this - one Thread to continously generate customers and queue them up and another thread pool of 5 threads that keep processing them.
0
 

Author Comment

by:jjackson2004
ID: 34118091
How does one do threads?
0
 
LVL 20

Assisted Solution

by:a_b
a_b earned 375 total points
ID: 34118179
Have a look at this - http://www.java2s.com/Code/Java/Threads/ThreadPoolTest.htm

The programs creates a ThreadPool and keeps submitting tasks there.
0
 

Author Closing Comment

by:jjackson2004
ID: 34174245
Thank you for your assistance.  This question is now moot.  I divided up points to those who helped.

0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now