предупреждения о переполнении для длинных преобразований в целые числа после обновления до 64 бит java - PullRequest
0 голосов
/ 12 июля 2020
• 1000 Но наш java был 32-битным, и поэтому мы преобразовывали long в массив из 4 байтов.
   private static byte[] longToBytes(final long value) {
        
        final byte[] bytes = new byte[4];

        for (int i = 0; i < bytes.length; ++i) {
            final int offset = (bytes.length - i - 1) * 8;
            bytes[i] = (byte) (((value & (0xff << offset)) >>> offset));
        }
        return bytes;
    }

Но теперь, когда java обновлен до 64-битного, мы получаем предупреждение об этом преобразование из укрытия. Это выражение вычисляется с использованием 32-битного airthmati c и затем используется в типе long. Так что может произойти потеря информации.

Теперь я не хочу использовать массив байтов с 8 байтами. Bcoz Я не знаю, что он сделает с нашим базовым протоколом и как он ожидает размер массива байтов. Но я хотел знать, в каком случае это может вызвать проблемы. Дата может быть 64-битной? Есть мысли о возможных проблемах при использовании этого кода?

Ответы [ 2 ]

1 голос
/ 12 июля 2020

в миллисекундах мы представляем дату

Какие числа вы можете представить в 4 байтах - 32 бита - зависит от того, интерпретирует ли их получатель как число со знаком или без знака.

  • 32-битное целое число со знаком изменяется от -2147483648 до 2147483647. Если эти числа являются миллисекундами с начала эпохи, вы можете представлять дату и время с 1969-12-07T03: 28: 36.352Z до 1970-01. -25T20: 31: 23.647Z. Это довольно узкий диапазон для большинства приложений. Мне кажется, что у вас очень реальная проблема, и мне интересно, как это могло go остаться незамеченным.
  • Если число без знака, даты и время могут go до 1970-02-19T17 : 02: 47.295Z. Это все еще немного больше 50 лет go.

Для сравнения, время сейчас представлено как 1_594_564_976_456 миллисекунд с начала эпохи. Требуется 41 бит, чтобы представить это число как беззнаковое число, или 42 бита, если оно подписано (они сказали, что ответ был 42? ;-) Итак, по крайней мере, 6 байтов.

И вы правы, он, вероятно, выиграл 'не решил отправить 6 или 8 байтов, когда получатель ожидает 4. Решение потребует больше.

1 голос
/ 12 июля 2020

Тип long был 64-битным с момента выхода первой версии java 25+ лет назад go. То же самое и для Date: он всегда использовал 64-битное значение для подсчета миллисекунд, начиная с эпохи Unix 1 января 1970 года. Целевая архитектура JVM (32/64 бит) здесь не играет роли.

Ваш новый инструмент качества кода предупреждает, что объединение типов int и long в битовой арифметике c может иметь неожиданные результаты. Я предполагаю, что он предпочел бы, чтобы вы написали код как:

final long offset = (bytes.length - i - 1L) * 8L;
bytes[i] = (byte) (((value & (0xffL << offset)) >>> offset));

Я обеспокоен тем, что этот код использует только младшие 4 байта значения даты long. Если вы используете миллисекундные метки времени, вы теряете информацию при этом преобразовании. Например, текущая метка времени (в шестнадцатеричном формате) - 17342e07b15, и вы отправляете 42e07b15 в качестве вывода.

...