Skip to content

Commit 7f49d93

Browse files
authored
Merge pull request #409 from msgpack/android4-pack-string
Avoid using CharsetEncoder of Android 4.x
2 parents 78d8bb3 + f536c93 commit 7f49d93

File tree

1 file changed

+46
-2
lines changed

1 file changed

+46
-2
lines changed

msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
import java.io.Closeable;
2323
import java.io.Flushable;
2424
import java.io.IOException;
25+
import java.lang.reflect.Constructor;
26+
import java.lang.reflect.Field;
27+
import java.lang.reflect.InvocationTargetException;
2528
import java.math.BigInteger;
2629
import java.nio.ByteBuffer;
2730
import java.nio.CharBuffer;
@@ -130,6 +133,46 @@
130133
public class MessagePacker
131134
implements Closeable, Flushable
132135
{
136+
private static final boolean CORRUPTED_CHARSET_ENCODER;
137+
138+
static {
139+
boolean corruptedCharsetEncoder = false;
140+
try {
141+
Class<?> klass = Class.forName("android.os.Build$VERSION");
142+
Constructor<?> constructor = klass.getConstructor();
143+
Object version = constructor.newInstance();
144+
Field sdkIntField = klass.getField("SDK_INT");
145+
int sdkInt = sdkIntField.getInt(version);
146+
// Android 4.x has a bug in CharsetEncoder where offset calculation is wrong.
147+
// See
148+
// - https://github.com/msgpack/msgpack-java/issues/405
149+
// - https://github.com/msgpack/msgpack-java/issues/406
150+
// Android 5 and later and 3.x don't have this bug.
151+
if (sdkInt >= 14 && sdkInt < 21) {
152+
corruptedCharsetEncoder = true;
153+
}
154+
}
155+
catch (ClassNotFoundException e) {
156+
// This platform isn't Android
157+
}
158+
catch (NoSuchMethodException e) {
159+
e.printStackTrace();
160+
}
161+
catch (IllegalAccessException e) {
162+
e.printStackTrace();
163+
}
164+
catch (InstantiationException e) {
165+
e.printStackTrace();
166+
}
167+
catch (InvocationTargetException e) {
168+
e.printStackTrace();
169+
}
170+
catch (NoSuchFieldException e) {
171+
e.printStackTrace();
172+
}
173+
CORRUPTED_CHARSET_ENCODER = corruptedCharsetEncoder;
174+
}
175+
133176
private final int smallStringOptimizationThreshold;
134177

135178
private final int bufferFlushThreshold;
@@ -675,8 +718,9 @@ public MessagePacker packString(String s)
675718
packRawStringHeader(0);
676719
return this;
677720
}
678-
else if (s.length() < smallStringOptimizationThreshold) {
679-
// Using String.getBytes is generally faster for small strings
721+
else if (CORRUPTED_CHARSET_ENCODER || s.length() < smallStringOptimizationThreshold) {
722+
// Using String.getBytes is generally faster for small strings.
723+
// Also, when running on a platform that has a corrupted CharsetEncoder (i.e. Android 4.x), avoid using it.
680724
packStringWithGetBytes(s);
681725
return this;
682726
}

0 commit comments

Comments
 (0)