Код: Выделить всё
var thread = new Thread(() -> {
var classLoader = My_Small_Class_Of_The_Same_Plugin.getClass().getClassLoader();
try {
classLoader.loadClass("My_Super_Big_Interface");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
});
thread.start();
Почему это не работает таким образом? Есть ли способ загрузить класс/интерфейс независимо от основного потока/UI потока?
Обратите внимание: я не хочу обсуждать размер интерфейса и то, что его следует разделить на несколько интерфейсов или классов. К сожалению, так дано и мне приходится с этим бороться.
Я обнаружил, что есть проблема с реализацией JVM (в моем случае OpenJDK 21). Когда загрузчик классов начинает загрузку с использованием собственного метода defineClass1(ClassLoader loader, ...); (см.: OpenJDK ClassLoader.java), он приостанавливает каждый поток до тех пор, пока выполняется определение класса. Это как минимум удивительно. Еще более удивительно то, что загрузка класса размером около 1,5 МБ, который не ссылается ни на какие другие классы или интерфейсы, занимает около 10 секунд. Вот небольшой пример (1 класс + 1 интерфейс) того, как его можно воспроизвести:
- : Поскольку интерфейс слишком велик для публикации его здесь, сгенерируйте его самостоятельно, используя следующий или собственный код:
Код: Выделить всё
My_Super_Big_InterfaceМожет ли кто-нибудь проверить результат на своей машине? Пожалуйста, запустите код и не запускайте его в режиме отладки.Код: Выделить всё
/** * Generates a big interface with a huge number of fields. * * @param args */ public static void main(String[] args) { var NUMBER_OF_FIELDS = 40000; var fields = ""; for (var i = 1; i { var i = 1; while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("\t\tLoop thread: " + i++ + ". round: " + LocalDateTime.now()); } }).start(); System.out.println("Loop thread started at: " + LocalDateTime.now()); // 2) start the class loading thread which pauses the other threads var class_Loading_Thread = new Thread(() -> { var classLoader = MainClass.class.getClassLoader(); try { var start_Millis = System.currentTimeMillis(); System.out.println("Before class loading: " + LocalDateTime.now()); // start the loading which causes every thread to pause classLoader.loadClass("com.test.My_Super_Big_Interface"); // 11:24:41.438144700
Может ли кто-нибудь запустить его в другой реализации JVM?
Я пытался найти ответственный код в реализации OpenJDK, начиная здесь: java.base.share.native.libjava.ClassLoader.c, но до сих пор я его не нашел.
После нескольких тестов кажется, что затраты времени определение класса/загрузка класса экспоненциально зависит от количества полей/членов. Например, для 20000 полей требуется 2 секунды, для 30000 – 6 секунд, для 40 000 – 10 секунд и для 65 000 – 30 секунд.
Подробнее здесь: https://stackoverflow.com/questions/798 ... -a-backgro
Мобильная версия