首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java Applet的内存消耗

问Java Applet的内存消耗
EN

Stack Overflow用户
提问于 2018-10-29 11:39:55
回答 2查看 82关注 0票数 0

在我的applet中,我接到了从远程位置下载文件的电话。当我试图下载大约13 my的大型文件时,我的Applet内存消耗将增加超过50 my。我使用以下代码来获得内存消耗:

代码语言:javascript
复制
public static long getMemoryUsage()
{
    long memory = 0;
    // Get the Java runtime
    Runtime runtime = Runtime.getRuntime();
    memory = runtime.totalMemory() - runtime.freeMemory();
    return memory;
}

我的get电话代码是

代码语言:javascript
复制
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();之后,applet的内存消耗至少增加了50 to,尽管我试图下载的文件只有13 to。

哪里有内存泄漏吗?

编辑:添加了getBytesFromInputStream()的实现

代码语言:javascript
复制
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();
    }
EN

回答 2

Stack Overflow用户

发布于 2018-10-29 12:09:05

因为这句话:

代码语言:javascript
复制
 byte []downloadedData = getBytesFromInputStream(objInputStream, count,fileSize);

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

大文件不应该被完整地读取到内存中,而应该直接流到数据的某个处理器。

票数 1
EN

Stack Overflow用户

发布于 2018-10-30 08:57:11

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

代码语言:javascript
复制
  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。)

不幸的是,您(显然)试图获得的大小是不正确的。

代码语言:javascript
复制
  int count = objInputStream.available();

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

如果服务器在响应中设置Content-Length头,那么您可以使用它;在获得响应后调用getContentLength() (或其他用例中的getContentLengthLong() )。但是,请做好准备,在这种情况下,这会给您-1。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53044755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档