Подтвердить что ты не робот

Почему java.lang.Object.getClass() (и отражение) работает медленнее, чем обычно?

Мы сталкиваемся с некоторыми странными проблемами производительности JVM.

У нас есть большой и несколько непрозрачный компонент GUI (таблица Excel 1).

Если мы инициализируем все это из Thread Dispatch Thread (как и должно быть), мы обнаруживаем, что код работает значительно медленнее (перетаскивая мышь, чтобы выбирать ячейки, там заметное отставание).

Если мы инициализируем его в первый раз в основном потоке запуска, и только затем начнем использовать его в EDT, он работает намного быстрее.

Когда я смотрю, почему он медленно работает с использованием профилировщика, все вызовы метода, которые принимают все время:

  • java.lang.Object.getClass()
  • java.lang.reflect.Array.newInstance(класс, int)
  • java.lang.Class.getComponentType()
  • java.lang.Thread.currentThread()

Мы используем 64-битную JVM Sun Hotspot для Windows 7 (тот, который поставляется с JDK).

Кто-нибудь знает о какой-либо причине, почему вышеупомянутые методы могут выполнять значительно медленнее, чем обычно?

Я думаю, что, возможно, это имеет какое-то отношение к порядку загрузки классов... это разумная теория? Кто-нибудь знает какие-либо другие способы, с помощью которых я могу диагностировать, почему эти вызовы методов могут занимать много времени?

Я добавил два скриншота из профилировщика. В обоих случаях все, что я делал, было перетаскивание мыши вокруг ячеек электронных таблиц во время работы профайлера. Таким образом, он просто обновляет компонент GUI и не делает ничего другого.

Первый из них проводит много времени в методе "releaseLock()". По какой-то причине это занимает много времени, потому что "getComponentType()" занимает гораздо больше времени, чем обычно.

releaseLock

Второй из них после того, как я сделал "взломать", чтобы удалить стоимость "releaseLock()", - но теперь он просто проводит много времени в "getLock()" из-за того, что getClass() и currentThread() принимают много дольше обычного:

getLock

Но важно то, что если я просто изменил порядок, в котором инициализируется код, ни один из этого кода не займет много времени (он вообще не отображается в профилировщике).

Если бы я должен был оптимизировать getLock(), приложение все равно выполняет гораздо медленнее. Кажется, что проблема заключается в том, что такие методы, как getClass(), занимают слишком много времени. Невозможно компенсировать это - getClass() вызывается в слишком многих местах!

Разница в производительности заметна даже без использования профайлера.

Также помните, что мы не можем изменить какой-либо из этих кодов - это внешний компонент. Задача состоит в том, чтобы объяснить, почему в некоторых случаях код выполняется намного медленнее, чем другие.

4b9b3361

Ответ 1

Вы можете попытаться взять несколько смешанных (java + native) jstack -m потоков дампов приложения под нагрузкой.

Это, вероятно, даст некоторые намеки на то, что происходит под капотом Object.getClass().

См. также Если профилировщик не является ответом, какие у нас есть другие варианты?

Также посмотрите Что такое дамп потока, когда JVM провела время в GC. Причина, по которой обычные дампы потоков JVM могут быть не совсем точными, поскольку они происходят только на safepoints.