2010-07-24 2 views
1

От PMD:ли примитивная обертка инстанцирование распределения причины памяти в JDK 1.6

IntegerInstantiation: В JDK 1.5, вызывающей новый Integer() вызывает выделение памяти. Integer.valueOf() больше совместим с памятью.

ByteInstantiation: В JDK 1.5 вызов нового байта() вызывает выделение памяти. Byte.valueOf() больше совместим с памятью.

ShortInstantiation: В JDK 1.5 вызов нового Short() вызывает выделение памяти. Short.valueOf() больше совместим с памятью.

LongInstantiation: В JDK 1.5 вызов нового Long() вызывает выделение памяти. Long.valueOf() больше совместим с памятью.

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

ответ

3

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

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

В свете этого маловероятно, что такая оптимизация будет стоить реализации:

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

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

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

1

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

2

Это относится и к 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)); 

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

0

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

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

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

0

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