Вызывает ли примитивная реализация оболочки выделение памяти в JDK 1.6 - PullRequest
2 голосов
/ 24 июля 2010

Из PMD:

IntegerInstantiation: в JDK 1.5 вызов нового Integer () вызывает выделение памяти.Integer.valueOf () более дружественен к памяти.

ByteInstantiation: в JDK 1.5 вызов new Byte () вызывает выделение памяти.Byte.valueOf () более дружественен к памяти.

ShortInstantiation: в JDK 1.5 вызов new Short () вызывает выделение памяти.Short.valueOf () более дружественен к памяти.

LongInstantiation: в JDK 1.5 вызов new Long () вызывает выделение памяти.Long.valueOf () более дружественный к памяти.

Применимо ли это к JDK 1.6?Мне просто интересно, оптимизируют ли компилятор или jvm это для своих соответствующих valueof методов.

Ответы [ 5 ]

3 голосов
/ 24 июля 2010

Теоретически, компилятор может оптимизировать небольшое подмножество случаев, когда (например) new Integer(n) использовалось вместо рекомендованного Integer.valueOf(n).

Во-первых, мы должны отметить, что оптимизация может быть применена только в том случае, если компилятор может гарантировать, что объект-оболочка никогда не будет сравниваться с другими объектами, использующими == или !=. (Если это произошло, тогда оптимизация изменяет семантику объектов-оболочек, так что «==» и «! =» Будут вести себя так, что это противоречит JLS.)

В свете этого вряд ли стоит проводить такую ​​оптимизацию:

  1. Оптимизация поможет только плохо написанным приложениям, которые игнорируют рекомендации javadoc и т. Д. Для хорошо написанного приложения тестирование на предмет возможности применения оптимизации только замедляет работу оптимизатора; например JIT-компилятор.

  2. Даже для плохо написанного приложения ограничение на то, где разрешена оптимизация, означает, что лишь немногие из реальных вызовов new Integer(n) соответствуют требованиям для оптимизации. В большинстве случаев слишком дорого отслеживать все места, где может использоваться оболочка, созданная выражением new. Если вы включите отражение на картинке, отслеживание практически невозможно для чего-либо, кроме локальных переменных. Поскольку большинство применений примитивных оболочек влечет за собой помещение их в коллекции, легко увидеть, что оптимизация вряд ли когда-либо будет найдена (с помощью практического оптимизатора).

  3. Даже в тех случаях, когда оптимизация действительно применялась, это помогло бы только для значений n в пределах ограниченного диапазона. Например, вызов Integer.valueOf(n) для большого n всегда создаст новый объект.

2 голосов
/ 24 июля 2010

Это относится и к Java 6. Попробуйте следующее с Java 6, чтобы доказать это:

System.out.println(new Integer(3) == new Integer(3));
System.out.println(Integer.valueOf(3) == Integer.valueOf(3));

System.out.println(new Long(3) == new Long(3));
System.out.println(Long.valueOf(3) == Long.valueOf(3));

System.out.println(new Byte((byte)3) == new Byte((byte)3));
System.out.println(Byte.valueOf((byte)3) == Byte.valueOf((byte)3));

Однако при больших числах оптимизация выключена, как и ожидалось.

1 голос
/ 24 июля 2010

То же самое относится и к Java SE 6. В целом, трудно оптимизировать создание новых объектов.Гарантируется, что, скажем, new Integer(42) != new Integer(42).В некоторых случаях существует возможность полностью исключить необходимость получения объекта, но я считаю, что все, что отключено в производственных сборках HotSpot на момент написания.

0 голосов
/ 24 июля 2010

В недавнем jvm с анализом escape и скалярной заменой, new Integer() может фактически быть быстрее, чем Integer.valueOf(), когда область действия переменной ограничена одним методом или блоком.См. Автобокс против ручного бокса в Java для получения более подробной информации.

0 голосов
/ 24 июля 2010

Большую часть времени это не имеет значения. Если вы не определили, что запускаете критический фрагмент кода, который вызывается много раз (например, 10 КБ или более), скорее всего, это не будет иметь большого значения.

Если есть сомнения, предположим, что компилятор не выполняет оптимизацию. Это на самом деле очень мало. Однако JVM может выполнять много оптимизаций, но устранение необходимости создания объекта не входит в их число. Общее предположение состоит в том, что распределение объектов в большинстве случаев происходит достаточно быстро.

Примечание: код, который запускается всего несколько раз (по умолчанию <10 КБ), даже не будет полностью скомпилирован с собственным кодом, и это может замедлить ваш код больше, чем выделение объектов. </p>

...