2017-01-17 7 views
0

Нам нужно послать действительно огромные сообщения SOAP (multiparts, MTOM), скажем около 1 или 2 гигабайт. Иногда процесс заканчивается следующим ООМ:Использование кучи в результате внедрения IBM SAAJ

java.lang.OutOfMemoryError: Java Heap Space 
at java.util.Arrays.copyOf(Arrays.java:2479) 
at java.io.ByteArrayOutputStream.toByteArray(ByteArrayOutputStream.java:203) 
at com.ibm.ws.webservices.engine.transport.channel.OutboundOutputStream.toByteArray(OutboundOutputStream.java:100) 
at com.ibm.ws.webservices.engine.transport.http.HttpOutboundChannelConnection.prepareHttpRequestHeaders(HttpOutboundChannelConnection.java:2027) 
at com.ibm.ws.webservices.engine.transport.http.HttpOutboundChannelConnection.sendSOAPRequest(HttpOutboundChannelConnection.java:374) 
at com.ibm.ws.webservices.engine.transport.http.HTTPSender.invoke(HTTPSender.java:745) 
at com.ibm.ws.webservices.engine.PivotHandlerWrapper.invoke(PivotHandlerWrapper.java:264) 
at com.ibm.ws.webservices.engine.PivotHandlerWrapper.invoke(PivotHandlerWrapper.java:264) 
at com.ibm.ws.webservices.engine.WebServicesEngine.invoke(WebServicesEngine.java:336) 
at com.ibm.ws.webservices.engine.client.Connection.invokeEngine(Connection.java:970) 
at com.ibm.ws.webservices.engine.client.Connection.invoke(Connection.java:761) 
at com.ibm.ws.webservices.engine.soap.SOAPConnectionImpl.call(SOAPConnectionImpl.java:223) 
at com.ibm.ws.webservices.engine.soap.SOAPConnectionImpl.call(SOAPConnectionImpl.java:163) 

На моем понимании, эта проблема связана с использованием ByteArrayOutputStream, который выглядит неуместным при работе с очень большими потоками.

Следуя таблице stacktrace, в куче требуется не менее 2 копий всего содержимого сообщения (в виде байтовых массивов).

Итак, вопрос, знает ли кто-нибудь о лучшей реализации SAAJ, посредством кучного потребления? Или может быть обходным путем для этой реализации IBM SAAJ?

ответ

1

Предполагая, что реализация IBM SAAJ не является полностью безумной, я ожидал бы, что она только преобразует сообщение в массив байтов, если HTTP-chunking не включен и ему нужно вычислить длину сообщения перед его отправкой. Поэтому первое, что нужно сделать, - убедиться, что функция chunking включена.

Я не думаю, что SAAJ определяет стандартный способ включения комков, но вы можете попробовать установить соответствующий заголовок HTTP на сообщение:

soapMessage.getMimeHeaders().addHeader("Transfer-Encoding", "chunked"); 

Скорее всего, что реализация SAAJ почтит это.

+0

У меня была такая же мысль, потому что chunking не включен и заголовок Content-Length присутствует до сих пор. Но все же я не имею четкого представления о том, как заставить там куски. Протокол, объявленный в запросе, является HTTP1.1, поэтому он должен быть весьма вероятным. – user3714601

+0

Я обновил ответ с предложением о том, как вы должны пытаться включить chunking. –

+0

К сожалению, нет, это не имеет никакого эффекта, если мы попытаемся установить такой заголовок напрямую. Грустно, но, наконец, нам пришлось переключиться с SAAJ на JAX-WS, который правильно обрабатывает огромные сообщения. – user3714601