简体   繁体   English

Java Applet的内存消耗

[英]Memory Consumption by Java Applet

In my applet I have GET call to download file from a remote location. 在我的applet中,我有GET调用,可以从远程位置下载文件。 When I am trying to download some large file of around 13MB, then my Applet memory consumption is increasing more than 50MB. 当我尝试下载大约13MB的大文件时,Applet的内存消耗增加了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 我的get呼叫的代码是

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(); 在上面的方法中,我尝试将日志用于内存消耗,并将其放在每行之后, conn.connect(); , the memory consumption of applet increases by atleast 50MB even though the file I am trying to download is only 13MB. ,即使我要下载的文件只有13MB,小程序的内存消耗也至少增加了50MB。

Is there any memory leak anywhere? 哪里有内存泄漏?

EDIT: Added Implementation for getBytesFromInputStream() 编辑:为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();
    }

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. 也许您正在将其复制到某个地方,即使您不再使用对该对象的引用,GC也需要一些时间才能启动。

Large files should never be read completly to memory, but rather streamed directly to some processor of the data. 大文件绝对不应完整地读取到内存中,而应直接流式传输到数据的某些处理器。

The only way to optimize getBytesFromInputStream() is if you know beforehand exactly how many by bytes there are to read. 优化getBytesFromInputStream()的唯一方法是,如果您事先确切知道要读取的字节数。 Then you allocate a byte[] of the required size, and read from the input directly into the byte[] . 然后,分配所需大小的byte[] ,然后从输入中直接读取到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 .) (有关更多信息,请阅读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; 如果服务器在响应中设置了Content-Length标头,则可以使用该标头。 call getContentLength() (or getContentLengthLong() in other use-cases) once you have the response. 调用getContentLength()getContentLengthLong()在其他使用情况),一旦你有响应。 But be prepared for the case where that gives you -1 . 但是要准备好让您得到-1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM