" " JVM. , , , HTTP- :
retrofit.RetrofitError: Java heap space
at retrofit.RetrofitError.unexpectedError(RetrofitError.java:44)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:400)
at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at retrofit.Platform$Base$2$1.run(Platform.java:94)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:421)
at java.lang.StringBuffer.append(StringBuffer.java:272)
at java.io.StringWriter.write(StringWriter.java:101)
at com.google.gson.stream.JsonWriter.open(JsonWriter.java:327)
at com.google.gson.stream.JsonWriter.beginObject(JsonWriter.java:308)
at q1.Q1$1$1.write(Q1.java:39)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJson(Gson.java:648)
at com.google.gson.Gson.toJson(Gson.java:603)
at com.google.gson.Gson.toJson(Gson.java:583)
at retrofit.converter.GsonConverter.toBody(GsonConverter.java:80)
at retrofit.RequestBuilder.setArguments(RequestBuilder.java:375)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:298)
... 7 more
:
- JVM:
-Xms4m -Xmx8m - -:
npm install http-echo-server -g && export PORT=8080 && http-echo-server ( . HTTP-, POST?)
? , , , StringWriter, ( , StringBuffer - ). :
interface IService {
@POST("/")
void query(@Body String s, Callback<String> callback);
}
final int floodLength = 1024 * 1024;
final TypeAdapterFactory flooder = new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
return new TypeAdapter<T>() {
@Override
public void write(final JsonWriter out, final T value)
throws IOException {
out.beginArray();
for ( int i = 0; i < floodLength; i++ ) {
out.beginObject();
out.endObject();
}
out.endArray();
}
@Override
@SuppressWarnings("unchecked")
public T read(final JsonReader in)
throws IOException {
loop:
for ( ; ; ) {
final JsonToken token = in.peek();
switch ( token ) {
case BEGIN_ARRAY: in.beginArray(); break;
case END_ARRAY: in.endArray(); break;
case BEGIN_OBJECT: in.beginObject(); break;
case END_OBJECT: in.endObject(); break;
case NAME: in.nextName(); break;
case STRING: in.nextString(); break;
case NUMBER: in.nextDouble(); break;
case BOOLEAN: in.nextBoolean(); break;
case NULL: in.nextNull(); break;
case END_DOCUMENT: break loop;
default: throw new AssertionError("no case for " + token);
}
}
return (T) "<mock>";
}
};
}
};
final Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(flooder)
.create();
final RestAdapter retrofit = new Builder()
.setEndpoint("http://localhost:8080/")
.setConverter(new GsonConverter(gson))
.build();
final IService service = retrofit.create(IService.class);
service.query("foo", new Callback<String>() {
@Override
public void success(final String string, final Response response) {
System.out.println("OK: " + string);
System.exit(0);
}
@Override
public void failure(final RetrofitError retrofitError) {
retrofitError.printStackTrace(System.err);
System.exit(1);
}
});
Writer , , , ( , , ). , , , - StringWriter - , - : , OutputStreamWriter OutputStream, , .. GsonConverter, Retrofit v1 ( Retrofit v2), , . , Gson Converter , :
final class StreamingGsonConverter
implements Converter {
private static final Charset charset = StandardCharsets.UTF_8;
private static final String MIME_TYPE = "application/json; charset=" + charset;
private final Gson gson;
StreamingGsonConverter(final Gson gson) {
this.gson = gson;
}
@Override
public Object fromBody(final TypedInput body, final Type type)
throws ConversionException {
try {
final Reader reader = new InputStreamReader(body.in(), charset);
return gson.fromJson(reader, type);
} catch ( final IOException ex ) {
throw new ConversionException(ex);
}
}
@Override
public TypedOutput toBody(final Object object) {
return new BodyTypedOutput(object);
}
private final class BodyTypedOutput
implements TypedOutput {
private final Object object;
private BodyTypedOutput(final Object object) {
this.object = object;
}
@Override
public String fileName() {
return null;
}
@Override
public String mimeType() {
return MIME_TYPE;
}
@Override
public long length() {
return -1;
}
@Override
public void writeTo(final OutputStream out) {
final Appendable appendable = new OutputStreamWriter(out, charset);
gson.toJson(object, appendable);
}
}
}
GsonConverter :
.setConverter(new StreamingGsonConverter(gson))
JSON- (- , HTTP- POST), ( HTTP- - ). , , , . !