【问题标题】:How to avoid OutOfMemoryError uploading file?如何避免 OutOfMemoryError 上传文件?
【发布时间】:2010-10-19 08:18:43
【问题描述】:

我正在尝试上传图片文件。当上传大小约为 40 到 200kb 的文件时,一切都很好。但是当我尝试上传大小为 459kb 的文件时,有时它会被上传,有时会显示 OutOfMemoryError。我认为抛出此错误的文件大小不会很大。我用的是树脂。是否有可能存在阻止上传大文件的树脂设置?因为在代码中我没有为文件上传设置任何最大大小。

任何人都知道如何避免这种情况。我希望用户上传大小不超过 10 MB 的图片。

【问题讨论】:

    标签: java resin


    【解决方案1】:

    如果内存不足,首先要检查的是 JVM 分配了多少内存。您没有说明 Resin 是如何运行的,或者它正在使用哪个 JVM 或操作系统/主机,但通常 JVM 将由默认堆大小和最大堆大小控制。从命令行来看,标准 JVM 具有控制这些值的 -Xms-Xmx 参数。当 JVM 启动时,它会分配默认堆,并允许它增长到最大值。当分配超过最大堆时,它可能会尝试释放任何软/弱引用和其他一次性资源,强制进行 GC,但如果它仍然没有足够的空间,它将抛出 OutOfMemoryException。因此,更改值可能会影响发生这种情况的时间。

    要寻找的第二件事是如何在服务器中分配内存。例如,如果您的服务器在内存中保存了一堆具有强引用的东西,您可能会耗尽内存,如果是这样,请考虑使用弱引用或类似Ehcache 的东西将东西移出磁盘。或者,如果您的 servlet 由于某种计算错误而分配 MB 而不是 KB。无论如何,您不应该尝试将整个输入读入内存。假设您正在实现一个 servlet,那么提供的 ServletRequest / HttpServletRequest 允许您访问 POSTDATA 的输入流,并且您可以分块读取它(例如,一次 32KB)并将其写入输出缓冲区块。作为一般经验法则,以离散块读取输入数据无论如何都是更好的做法,因为您不希望不受信任的数据能够通过向您传递一些大文件来破坏您的服务器。

    【讨论】:

    • 谢谢。你能告诉我在哪里可以在树脂中设置这个 -Xms 参数吗?我正在使用 jvm 1.5。还有一种方法可以在不增加堆空间的情况下上传文件。我已经在使用 inputstream 读取文件。(我正在使用 struts 并使用 struts 中的 FormFile)
    • 这取决于您如何启动它,但 Caucho 有一些调整信息可能会有所帮助。在树脂 4.0 中,有一个 resin.xml,您可以在其中指定 JVM 参数 - caucho.com/resin-4.0/admin/starting-resin-command-line.xtp
    【解决方案2】:

    OutOfMemoryError 在没有足够内存可用于特定操作(例如对象的实例化)时由 JVM 抛出

    为避免此类错误,您可以在启动时使用特定选项来增加 JVM 的可用内存,具体取决于您的 JVM(通常 -Xmx512m 表示 512 兆)

    在您的情况下,如此小的上传不应产生任何 OutOfMemoryError,我建议使用诸如 Memory Analyzer 之类的工具来确定错误的根源。

    【讨论】:

      【解决方案3】:

      在尝试启动应用程序时,设置堆和保留区域的最大和最小大小

      使用 Xmx Xms Xss

      【讨论】:

        【解决方案4】:

        我会发布这个因为它对我有帮助,我尝试摆弄 Tomcat 内存分配(我正在运行 Coldfusion 和 Lucee),但最后我通过从磁盘读取文件而不是从 cfimage(内存): 磁盘中的 SQL 语句摘录(已工作):

        <cfqueryparam value="#fileRead("#absFilePath#")#" cfsqltype="cf_sql_blob">,
        

        内存中的 SQL 语句摘录(文件较大时失败):

        #Load into cfimage
        <cfimage action="read" source="#absFilePath#" name="myImage">
        #Try to us it in cfqueryparam example:
        <cfqueryparam value="#ImageGetBlob(myImage)#" cfsqltype="cf_sql_blob">,
        

        我觉得非常奇怪的是,我仍然将较大的图像读入 cfimage,这样我就可以制作缩略图,这很好,但我必须使用 toBinary("Placeholder") 进行第一次插入,然后我可以设置缩略图,但随后我必须执行更新查询以将“占位符”替换为 fileRead。奇怪,但我现在测试了高达 2MB 的大小,这很好,而之前它在 ~400KB 时失败了。

        【讨论】:

          猜你喜欢
          • 2017-03-20
          • 1970-01-01
          • 2018-01-11
          • 2013-06-05
          • 2011-07-14
          • 1970-01-01
          • 2018-01-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多