Разные результаты на Oracle JRE и Dalvik JVM - PullRequest
1 голос
/ 02 января 2012

Я застрял при создании менеджера лицензий для приложения Android, где лицензионный ключ генерируется на настольном сервере, а код проверки запускается на устройствах Android. Код проверки при выполнении на рабочем столе дает желаемые результаты, но тот же код дает другой результат на Android.

Я отладил проблему и дошел до того, что результаты были получены!

Вот фрагмент кода, демонстрирующий разницу:

byte[] bytes = {-88, 50, -29, 114, 51, 88, 38, -52, 114, 91, -23, -55, 124, 37, -90, -49, 36, -110, -67, -59, -33, -75, 85, -72, -109, 25, -54, 89, 6, 35, -50, -11, -87, -22, 33, -2, 55, -30, 75, -36, -40, -29, -103, 110, 46, -100, -68, 101, -105, 62, 53, -20, -20, -21, -118, -72, -27, 32, 59, 127, 15, -117, 6, 102};
System.out.println(new String(bytes, "UTF-8").hashCode());

на oracle jdk результат получается

-24892055

но на андроид телефоне результат:

-186036018

Любая помощь будет оценена.

Ответы [ 2 ]

3 голосов
/ 02 января 2012

Когда вы вызываете getBytes (), вам также нужно указать здесь кодировку, в противном случае вы получите кодировку по умолчанию от ОС, которая может быть любой, например, showBytes(new String(bytes, "UTF-8").getBytes("UTF-8"));

2 голосов
/ 03 января 2012

Разница в том, как Android и Java работают с искаженным UTF-8.Учитывая четырехбайтовую последовательность 0xf5 0xa9 0xea 0x21, Android возвращает два символа замены Юникода (0xfffd).Библиотека классов Oracle возвращает три символа замены Unicode.

Вот более простой пример, демонстрирующий проблему.

byte[] bytes = { (byte) 0xf5, (byte) 0xa9, (byte) 0xea, (byte) 0x21 };
String decoded = new String(bytes, "UTF-8");
for (int i = 0; i < decoded.length(); i++) {
  System.out.print(Integer.toHexString(decoded.charAt(i)) + " ");
}

Печать Oracle JVM

fffd fffd fffd 

Печать dalvikvm для Android

fffd fffd

Лучше всего избегать декодирования последовательностей байтов с использованием UTF-8, если только вы не знаете, что это на самом деле UTF-8.Я сообщил об этом несоответствии команде Dalvik для расследования: ошибка Android 23831 .

Если вы используете CharsetDecoder, Android использует icu4c для выполнения преобразования.Это возвращает U + fffd U + fffd U + 0021, что также кажется правильным при прочтении спецификации UTF-8.В будущих выпусках Android String будет соответствовать Android CharsetDecoder 2 .

...