feign-form icon indicating copy to clipboard operation
feign-form copied to clipboard

Getting a "java.lang.OutOfMemoryError: Java heap space" when upload large (+1 GB) files

Open tmoreira2020 opened this issue 4 years ago • 4 comments

Hi there, after some researching and source code review I identified that there is low support to upload large files. I'm trying to upload a file bigger than 1GB and the following stacktrace pops up on my log.

java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3236)
	at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
	at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
	at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
	at feign.form.multipart.Output.write(Output.java:80)
	at feign.form.multipart.SingleFileWriter.write(SingleFileWriter.java:51)
	at feign.form.multipart.AbstractWriter.write(AbstractWriter.java:36)
	at feign.form.MultipartFormContentProcessor.process(MultipartFormContentProcessor.java:87)
	at feign.form.FormEncoder.encode(FormEncoder.java:105)
	at feign.ReflectiveFeign$BuildFormEncodedTemplateFromArgs.resolve(ReflectiveFeign.java:353)
	at feign.ReflectiveFeign$BuildTemplateByResolvingArgs.create(ReflectiveFeign.java:232)
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:84)
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100)
	at com.sun.proxy.$Proxy1131.uploadBackup(Unknown Source)

The uploadBackup method is defined like this:

    @Headers("Content-Type: multipart/form-data")
    @RequestLine("POST /backup/upload")
    Backup uploadBackup(@Param("database") File database, @Param("volume") File volume);

I identified that there is low support because the SingleFileWriter.write method loads the entire file into the memory. Are there any other configuration that I can use to fix or workaround this limitation issue?

Thanks

tmoreira2020 avatar Feb 06 '21 19:02 tmoreira2020

have you found a workaround that is not making the http request manually?

alecha avatar Jun 21 '21 16:06 alecha

yes, I used the RestTemplate from Spring Framework to upload the large files, I ended up with two clients implementations 🤦

tmoreira2020 avatar Jun 21 '21 21:06 tmoreira2020

Thanks @tmoreira2020 , I was able to use RestTemplate to upload large files but unable to make it work for downloading them, did you have the same need?

alecha avatar Jun 22 '21 16:06 alecha

The trick here (and this applies for any download/upload) is to take advantage of storage media (local hdd, s3, whatever) and keep in memory only a buffer. If keeping a gigabyte file in memory is unstable when running with single client in dev, imagine what's going to happen when there are several parallel downloads on prod? The correct solution is to keep in memory only a buffer and read it from and write it to a stream.

vstoyanov avatar Jun 15 '23 12:06 vstoyanov