1

不久前,我在下面的代码上寻求帮助,最后又开始研究它。基本上,我已将错误缩小到导致此错误的文件大小:

线程“主”java.lang.OutOfMemoryError 中的异常:Java 堆空间

堆栈跟踪中该错误正下方的行是: at java.util.Arrays.copyOf(Arrays.java:2786)

我可以向这个程序传递一个包含数千个小文件的大目录,但是任何超过 50 Mb 大小的文件都会崩溃。我没有追踪程序崩溃的确切大小,但我知道至少 50 Mb 的文件会导致问题。

下面是主要片段,堆栈跟踪告诉我我的代码正在破坏。

private void handleFile(File source)
{
    FileInputStream fis = null;

    try
    {
        if(source.isFile())
        {
            fis = new FileInputStream(source);
            handleFile(source.getAbsolutePath(), fis);
        }
        else if(source.isDirectory())
        {
            for(File file:source.listFiles())
            {
               if(file.isFile())
               {
                   fis = new FileInputStream(file);
                   handleFile(file, fis);
               }
               else
               {
                   handleFile(file);
               }
            }
         }
     }
     catch(IOException ioe)
     {
         ioe.printStackTrace();
     }
     finally
     {
         try
         {
             if(fis != null) { fis.close(); }
         }
         catch(IOException ioe) { ioe.printStackTrace(); }
     }
}

private handleFile(String fileName, InputStream inputStream)
{
    byte[] startingBytes = null;

    try
    {
       startingBytes = inputStreamToByteArray(inputStream);

       if(startingBytes.length == 0) return;

       if(isBytesTypeB(startingBytes))
       {
          do stuff
          return;
       }
     }
     catch(IOException ioe)
     {
         ioe.printStackTrace();
     }
}

private byte[] inputStreamToByteArray(InputStream inputStream)
{
    BufferedInputStream bis = null;
    ByteArrayOutputStream baos = null;

    try
    {
        bis = new BufferedInputStream(inputStream);
        baos = new ByteArrayOutputStream(bis);

        byte[] buffer = new byte[1024];

        int nRead;
        while((nRead = bis.read(buffer)) != -1)
        {
            baos.write(buffer, 0, nRead);
        }
    }
    finally { baos.close(); }

    return baos.toByteArray();
 }

 private boolean isBytesTypeB(byte[] fileBytes)
 {
     // Checks if these bytes match a particular type
     if(BytesMatcher.matches(fileBytes, fileBytes.length))
     {
         return true;
     }
     return false;
 }

所以上面的代码中有一些东西导致了错误。有什么想法我在这里做错了吗?

4

3 回答 3

2

Arrays.copyOf每次ByteArrayOutputStream的内部数组需要调整大小时调用。这是内存需求最高的时刻。您可以通过指定数组的初始大小等于文件大小来避免调整数组大小。

于 2013-05-08T17:38:45.607 回答
1

我还没有阅读您的所有代码,但是可以使用更多可用的堆空间来启动 Java

java -Xmx128m

例如。

于 2013-05-08T17:38:04.280 回答
1

您可以从 Windows> Preferences> Java> Installed JREs 增加堆空间,从那里选择 JRE 并单击编辑,然后在 Default VM Arguments: to -Xmx2048 中写入(它将分配 2gb)

于 2013-05-08T17:39:13.367 回答