【问题标题】:J2ME nokia s40 out of memory exceptionJ2ME nokia s40 内存不足异常
【发布时间】:2012-03-08 14:40:14
【问题描述】:

我正在尝试将 2mb 文件读入内存,然后将该文件发送到 Web 服务器。但是我的内存不足异常。

         FileConnection fileConn = (FileConnection)Connector.open("file:///" + pictureURI.getString(), Connector.READ);
     InputStream fis = fileConn.openInputStream();
     long overallSize = fileConn.fileSize();

     int chunkSize = 2048;
     int length = 0;
     while (length < overallSize)
     {

        byte[] data = new byte[chunkSize];
        int readAmount = fis.read(data, 0, chunkSize);
        byte[] newImageData = new byte[rawImage.length + chunkSize];
        System.arraycopy(rawImage, 0, newImageData, 0, length);
        System.arraycopy(data, 0, newImageData, length, readAmount);
        rawImage = newImageData;
        length += readAmount;

     }
       fis.close();
        fileConn.close(); 

500kb 文件正在上传。可能是什么原因?请对此有所了解。

我也在循环中尝试过,但没有用,System.gc();

[编辑] https://stackoverflow.com/users/45668/malcolm 让我走上了正轨。现在我来这里了

  this.progress = progress;

  HttpConnection conn = null;
  OutputStream os = null;
  InputStream s = null;
  StringBuffer responseString = new StringBuffer();

  try
  {
     System.out.println(System.getProperty("HTTPClient.dontChunkRequests"));
     conn = (HttpConnection)Connector.open(url);
     //conn.setRequestProperty("User-Agent", "Profile/MIDP-2.1 Configuration/CLDC-1.1");
     conn.setRequestMethod(HttpConnection.POST);

     // The messages
     conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=---------------------------4664151417711");
     conn.setRequestProperty("Content-Length", "355");

     os = conn.openOutputStream();

     System.out.println("file name at upload " + fileName);
     String message1 = "";
     message1 += "-----------------------------4664151417711\r\n";
     message1 += "Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n";
     message1 += "Content-Type: image/gif\r\n";
     message1 += "\r\n";

     os.write(message1.getBytes());

     System.gc();

     // Send the image
     int index = 0;
     int size = 2048;
     double progdouble;
     do
     {
        progdouble = ((double)index) / ((double)rawImage.length) * 100;
        progress.setValue((int)progdouble);

        if((index+size) > rawImage.length)
        {
           size = rawImage.length - index;
        }
        os.write(rawImage, index, size);
        index += size;

        System.gc();
     } while(index < rawImage.length);

     String message2 = "\r\n-----------------------------4664151417711\r\n";
     message2 += "Content-Disposition: form-data; name=\"number\"\r\n\r\n";
     message2 += this.user_phone_number;         

     os.write(message2.getBytes());

     String message3 = "\r\n-----------------------------4664151417711\r\n";
     message3 += "Content-Disposition: form-data; name=\"uuid\"\r\n\r\n";
     message3 += this.user_uuid;         

     os.write(message3.getBytes());

     String message4 = "\r\n-----------------------------4664151417711--\r\n";  

     os.write(message4.getBytes());


     os.flush();
     os.close();

     // Read

     s = conn.openInputStream();
     int ch, i = 0, maxSize = 16384;
     while(((ch = s.read())!= -1 ) & (i++ < maxSize)) 
     {
        responseString.append((char) ch);
     }

     conn.close();
     System.out.println("response =>"+responseString.toString());



     return responseString.toString();
  }
  catch (IOException ioe)
  {
     return ioe.toString();
  }

现在这里失败了..

[EDIT2]

// algorithm that will read 1024 bytes at a time 
        byte b[] = new byte[chunkSize];
        for (int i = 0; i < overallSize; i += chunkSize) { 

            if ((i + chunkSize) < overallSize) {
                fis.read(b, 0, chunkSize);
            } else {
                int left = (int)overallSize - i;
                fis.read(b, 0, left);
            }

            // writing into the output stream - ( these lines will cause the "memory leak", without these, it will not happen)
            os.write(b);
            System.gc(); 

            progdouble = ((double)i) / ((double)overallSize) * 100;
            progress.setValue((int)progdouble); 
        }
        os.flush();

提前致谢。

【问题讨论】:

    标签: java-me out-of-memory series-40


    【解决方案1】:

    您在此过程中分配了很多新数组,这完全没有必要。每个new byte[] 行分配一个新数组。

    您应该读入一个大数组,并且应该在循环之前分配一次。您可以轻松地做到这一点,因为您知道文件的确切大小。代码将如下所示:

    FileConnection fileConn;
    InputStream is;
    
    try {
        fileConn = (FileConnection) Connector.open("file:///" + pictureURI.getString(), Connector.READ);
        is = fileConn.openInputStream();
    
        long overallSize = fileConn.fileSize();
        if (overallSize > Integer.MAX_VALUE) throw new IllegalArgumentException("File is too large);
        byte[] imageData = new byte[(int) overallSize];
        int chunkSize = 2048;
        int bytesReadTotal = 0;
        while (bytesRead < overallSize) {
            int bytesRead = is.read(imageData, bytesReadTotal, Math.min(imageData.length - bytesReadTotal, chunkSize));
            if (bytesRead == -1) break;
            bytesReadTotal += bytesRead;
        }
    } finally {
        if (is != null) is.close();
        if (fileConn != null) fileConn.close();
    }
    

    【讨论】:

    • 感谢您的回复。我会检查并尽快回复您。
    • 你走上了正轨。现在我可以从读取文件继续前进,但是在上传时遇到同样的错误......请看一下这段代码。
    • 文件读取现在很好,但是当我尝试上传它时给我同样的错误。将数据读入数组然后将其刷新或立即读取并推送是一种更好的方法?
    • @VenuGopalT 如果您只想发送一个文件,当然,不要将整个文件加载到内存中,而是使用一个小缓冲区。您将部分数据读入其中,发送它,然后重复这些步骤,直到发送整个文件。
    • 我试过这个方法,但是在上传 60% 后仍然失败。好像这个设备(诺基亚 x2-01)不支持这个尺寸。我检查了其他有同样问题的视频上传应用。
    【解决方案2】:

    您的手机 (Nokia x2-01 specs) 被限制为整个应用程序的 2Mb 堆空间。根据这些限制设计您的应用程序。一次在内存中存储 2Mb 字节数组 - 不可能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      相关资源
      最近更新 更多