在我的applet中,我接到了从远程位置下载文件的电话。当我试图下载大约13 my的大型文件时,我的Applet内存消耗将增加超过50 my。我使用以下代码来获得内存消耗:
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();之后,applet的内存消耗至少增加了50 to,尽管我试图下载的文件只有13 to。
哪里有内存泄漏吗?
编辑:添加了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();
}发布于 2018-10-29 12:09:05
因为这句话:
byte []downloadedData = getBytesFromInputStream(objInputStream, count,fileSize);在这里,您正在将文件的全部字节读入堆中。在此之后,您需要跟踪这个数组发生了什么。也许您正在将其复制到某个地方,即使不再使用对对象的引用,GC也需要一些时间来启动。
大文件不应该被完整地读取到内存中,而应该直接流到数据的某个处理器。
发布于 2018-10-30 08:57:11
优化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。
https://stackoverflow.com/questions/53044755
复制相似问题