При работе с языком программирования Java, особенно при проведении различных бенчмарков, кодеры могут столкнуться с интересным явлением. Иногда возникает ситуация, когда код, скопированный из классов JDK (Java Development Kit) и запущенный в пользовательском пакете, работает медленнее, чем тот же код, вызванный напрямую из классов JDK.
// Код, скопированный из класса BigInteger и запущенный в пользовательском пакете BigInteger a = new BigInteger(s1 * 8, r), b = new BigInteger(s2 * 8, r); long tm1 = System.nanoTime(); BigInteger c = a.multiply(b);
В результате такого кода время выполнения операции будет значительно больше, чем при использовании кода, вызываемого напрямую из класса JDK.
// Код, вызываемый напрямую из класса BigInteger в JDK BigInteger a = new BigInteger(s1 * 8, r), b = new BigInteger(s2 * 8, r); long tm1 = System.nanoTime(); BigInteger c = a.multiply(b);
Это может показаться странным, ведь в теории код должен работать одинаково, независимо от того, где он запущен. Возникает вопрос: может ли JIT (Just-In-Time) компилятор Java «читерить», используя некие предварительно вычисленные оптимизации для кода JDK?
Ответ на этот вопрос прост. Нет, JIT компилятор Java не «читерит». Он оптимизирует код на основе статистики его выполнения. В случае с классами JDK, они, как правило, используются чаще, чем пользовательский код, и JIT компилятор имеет больше данных для их оптимизации.
Кроме того, важно понимать, что классы JDK загружаются классом загрузчика Bootstrap, который имеет преимущества перед пользовательскими загрузчиками классов. Один из этих преимуществ — возможность использования внутренних сфер JVM (Java Virtual Machine), которые недоступны для пользовательского кода.
Таким образом, разница в скорости работы кода, скопированного из классов JDK, и кода, вызываемого напрямую из этих классов, не является результатом «читерства» JIT компилятора, а обусловлена разницей в оптимизации и особенностях работы загрузчиков классов.
Добавить комментарий