Hello World
Hello World

Reputation: 239

Memory Consumption by Java Applet

In my applet I have GET call to download file from a remote location. When I am trying to download some large file of around 13MB, then my Applet memory consumption is increasing more than 50MB. I am using the below code to get my memory consumption:

public static long getMemoryUsage()
{
    long memory = 0;
    // Get the Java runtime
    Runtime runtime = Runtime.getRuntime();
    memory = runtime.totalMemory() - runtime.freeMemory();
    return memory;
}

Code for my get call is

public  void getFiles(String filePath, long fileSize)throws MyException
    {
        InputStream objInputStream = null;
        HttpURLConnection conn = null;
        BufferedReader br = null;
        try 
        {
            URL fileUrl=new URL(filePath);
            final String strAPICall=fileUrl.getPath();
            final String strHost="some.test.com";
            final int iPort=1000;
            URL url = null;
            url = new java.net.URL
                        ( "https",
                                strHost, iPort , "/" + strAPICall,
                                new myHandler() );  

            conn = (HttpURLConnection)new HttpsURLConn(url);
            conn.setRequestMethod("GET");

            conn.connect();

            if (conn.getResponseCode() != 200) {

                objInputStream=conn.getInputStream();

                br = new BufferedReader(new InputStreamReader(
                (objInputStream)));

                String output;
                while ((output = br.readLine()) != null) {
                    System.out.println(output);

                }
                throw new MyException("Bad response from server", 
                            MyError.BAD_RESPONSE_ERROR);

            }
            else
            {

                notifyProgressToObservers(0);
                System.out.println("conn.getResponseCode()"+conn.getResponseCode());
                System.out.println("conn.getResponseMessage()"+conn.getResponseMessage());
                objInputStream  = conn.getInputStream();
                int count=objInputStream.available();

                System.out.println("Stream size: "+count);
                System.out.println("fileSize size: "+fileSize);
                byte []downloadedData = getBytesFromInputStream
                        (objInputStream, count,fileSize);
                notifyChunkToObservers(downloadedData);
                notifyIndivisualFileEndToObservers(true, null);

            }

        }
        catch (MyException pm)
        {
            throw new MyException
            (pm, MyError.CONNECTION_TIMEOUT);
        }
        catch (IOException pm)
        {
            throw new MyException
            (pm, MyError.CONNECTION_TIMEOUT);
        }
        catch (Exception e) 
        {

            notifyIndivisualFileEndToObservers(false,new MyException(e.toString()));
        }
        finally
        {
            System.out.println("Closing all the streams after getting file");
            if(conn !=null)
            {
                try
                {
                    conn.disconnect();
                }
                catch(Exception e)
                {

                }
            }
            if(objInputStream != null)
            {
                try {
                    objInputStream.close();
                } catch (IOException e) {

                }
            }
            if (br != null) 
            {
                try {
                    br.close();
                } catch (IOException e) {

                }
            }
        }

    }

In the above method, I tried putting the log for memory consumption after each line and found that after conn.connect();, the memory consumption of applet increases by atleast 50MB even though the file I am trying to download is only 13MB.

Is there any memory leak anywhere?

EDIT: Added Implementation for getBytesFromInputStream()

public byte[] getBytesFromInputStream(InputStream is, int len, long fileSize)
            throws IOException 
    {
        byte[] readBytes= new byte[8192];
        ByteArrayOutputStream getBytes= new ByteArrayOutputStream();

        int numRead = 0;

        while ((numRead = is.read(readBytes)) != -1) {
            getBytes.write(readBytes, 0, numRead);
        } 


        return getBytes.toByteArray();
    }

Upvotes: 0

Views: 87

Answers (2)

Stephen C
Stephen C

Reputation: 718826

The only way to optimize getBytesFromInputStream() is if you know beforehand exactly how many by bytes there are to read. Then you allocate a byte[] of the required size, and read from the input directly into the byte[]. For example:

  byte[] buffer = new byte[len];
  int pos = 0;
  while (pos < len) {
     int nosRead = is.read(buffer, pos, len - pos);
     if (nosRead == -1) {
         throw new IOException("incomplete response");
     }
     pos += nosRead;
  }
  return buffer;

(For more information, read the javadoc.)

Unfortunately, your (apparent) attempt at getting the size is incorrect.

  int count = objInputStream.available();

This doesn't return the total number of bytes that can be read from the stream. It returns the number of bytes that can be read right now without the possibility of blocking.

If the server is setting the Content-Length header in the response, then you could use that; call getContentLength() (or getContentLengthLong() in other use-cases) once you have the response. But be prepared for the case where that gives you -1.

Upvotes: 1

markusw
markusw

Reputation: 2055

it's because of this line:

 byte []downloadedData = getBytesFromInputStream(objInputStream, count,fileSize);

here you are reading the complete amount of bytes of file into the heap. After that you need to track down what happens with this array. Maybe you are copying it somewhere and the GC needs some time to kick in even if you do not use the reference to the object anymore.

Large files should never be read completly to memory, but rather streamed directly to some processor of the data.

Upvotes: 1

Related Questions