Как показали мои эксперименты (java 1.7.0_01), код:
osw = new OutputStreamWriter(urlCon.getOutputStream());
osw.write("HELLO WORLD");
osw.flush();
Не отправляет ничего на сервер.Он просто сохраняет то, что там записано, в буфер памяти.Таким образом, если вы собираетесь загружать большой файл через POST - вы должны быть уверены, что у вас достаточно памяти.На десктопе / сервере это может быть не такой большой проблемой, но на андроиде это может привести к нехватке памяти.Вот пример того, как выглядит трассировка стека при попытке записи в выходной поток, и память заканчивается.
Exception in thread "Thread-488" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.util.Arrays.copyOf(Arrays.java:2271)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140)
at sun.net.www.http.PosterOutputStream.write(PosterOutputStream.java:78)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:282)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:135)
at java.io.OutputStreamWriter.write(OutputStreamWriter.java:220)
at java.io.Writer.write(Writer.java:157)
at maxela.tables.weboperations.POSTRequest.makePOST(POSTRequest.java:138)
В нижней части трассы вы можете увидеть метод makePOST()
, который выполняет следующее:
writer = new OutputStreamWriter(conn.getOutputStream());
for (int j = 0 ; j < 3000 * 100 ; j++)
{
writer.write("&var" + j + "=garbagegarbagegarbage_"+ j);
}
writer.flush();
И writer.write()
выдает исключение.Также мои эксперименты показали, что любое исключение, связанное с фактическим соединением / вводом-выводом с сервером, генерируется только после вызова urlCon.getOutputStream()
.Даже urlCon.connect()
кажется «фиктивным» методом, который не имеет никакой физической связи.Однако, если вы вызываете urlCon.getContentLengthLong()
, который возвращает поле заголовка Content-Length: из ответных заголовков сервера - тогда URLConnection.getOutputStream () будет вызываться автоматически, а в случае возникновения исключения - будет выброшено.все исключения, выдаваемые urlCon.getOutputStream()
, являются IOException, и я встретил следующие:
try
{
urlCon.getOutputStream();
}
catch (UnknownServiceException ex)
{
System.out.println("UnkownServiceException():" + ex.getMessage());
}
catch (ConnectException ex)
{
System.out.println("ConnectException()");
Logger.getLogger(POSTRequest.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException ex) {
System.out.println("IOException():" + ex.getMessage());
Logger.getLogger(POSTRequest.class.getName()).log(Level.SEVERE, null, ex);
}
Надеюсь, мое небольшое исследование поможет людям, так как класс URLConnection в некоторых случаях немного нелогичный, поэтомуРеализация - нужно знать, с чем это имеет дело.
Вторая причина: при работе с серверами - работа с сервером может быть неудачной по многим причинам (соединение, DNS, межсетевой экран, httpresponses, сервер не может принять соединение, сервер не может своевременно обработать запрос).Таким образом, важно понять , как возникшие исключения могут объяснить, что в действительности происходит с соединением .