繁体   English   中英

Java Applet的内存消耗

[英]Memory Consumption by Java Applet

在我的applet中,我有GET调用,可以从远程位置下载文件。 当我尝试下载大约13MB的大文件时,Applet的内存消耗增加了50MB以上。 我正在使用以下代码来获取内存消耗:

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

我的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) {

                }
            }
        }

    }

在上面的方法中,我尝试将日志用于内存消耗,并将其放在每行之后, conn.connect(); ,即使我要下载的文件只有13MB,小程序的内存消耗也至少增加了50MB。

哪里有内存泄漏?

编辑:为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();
    }

因为这条线:

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

在这里,您正在读取堆中文件的完整字节数。 之后,您需要跟踪此数组会发生什么。 也许您正在将其复制到某个地方,即使您不再使用对该对象的引用,GC也需要一些时间才能启动。

大文件绝对不应完整地读取到内存中,而应直接流式传输到数据的某些处理器。

优化getBytesFromInputStream()的唯一方法是,如果您事先确切知道要读取的字节数。 然后,分配所需大小的byte[] ,然后从输入中直接读取到byte[] 例如:

  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;

(有关更多信息,请阅读javadoc 。)

不幸的是,您(明显)的尝试获取大小是不正确的。

  int count = objInputStream.available();

这不会返回可以从流中读取的字节总数。 它返回现在可以读取而没有阻塞可能性的字节数。

如果服务器在响应中设置了Content-Length标头,则可以使用该标头。 调用getContentLength()getContentLengthLong()在其他使用情况),一旦你有响应。 但是要准备好让您得到-1

暂无
暂无

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

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